optimise  v.表示乐观,使优化
o欧弟 p婆婆  ti替  mi我  se蛇
欧弟的婆婆替我优化了贪吃蛇程序。
设计模式之单例模式

动机:
        有的时候一个类只有一个实例很重要,比如在一个系统里应该只有一个window manager。通常情况下,单例模式被用来集中管理内部或者外部资源。并提供一个全局的访问点。
目的:        确认一个类只有一个实例被创建。提供一个全局的访问点去访问该实例。
实现:    私有的构造函数和静态公共的全局访问点
class Singleton
{
    private static Singleton instance;
    private Singleton()
    {
        ...
    }
    public static synchronized Singleton getInstance()    //synchronized同步用来避免多线程创建多个实例
    {
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
    ...
    public void doSomething()
    {
        ...    
    }
}
public class MyRunable implements Runnable{
    @Override
    public void run() {
        System.out.println(Singleton.getInstance());
    }
}
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new MyRunable());
            thread.start();
        }
    }
适用和例子:
    一个类只能存在一个实例的时候用单例,通过全局的访问点去访问该实例,下面是一些例子:
Example 1: Logger Classes  日志类
    单例被用来设计日志类,日志通过全局访问点得到实例而不用每次去创建它。
Example 2; Configuration Classes 配置类
    单例被用来设计配置应用设置的配置类。通过用单例实现配置类,我们不仅提供全局的访问点,而且保持
该实例作为内存对象cache object。当这个类被实例化之后,这个单例就会在类的内部保存值。当这些值被从
数据库或者文件中读出来,这可以避免配置参数被使用的时候每次重新加载。
Example 3: Factories implemented as Singletons 用单例实现工厂模式
    假设我们设计一个在多线程环境中使用工厂模式通过它们的ids生成新对象的应用。如果这个工厂被实例化两次在
两个不同的线程,很可能产生两个一样的id产生两个不同的对象。如果我们使用单例去实现这个工厂,就可以避免
这个问题。将抽象工厂或者工厂方法同单例模式一起使用是个通常的做法。
说明问题和解决问题:
使用多线程的线程安全。
    之前通过用synchronized修饰getInstance()方法实现线程的标准做法,但是不是最好的线程安全实现,因为同步化(synchronized)是非常昂贵的,我们看到在通过同步实例化该对象的时候,我们没必要再用synchronezed方法去检查是否线程同步。
    所以最好的方法就是在一个非线程同步块(unsynchronized bolck)中去检查对象是否为空,如果为空,再从一个同步块(synchronized block)中创建一个对象。这种做法称之为Double Locking Mechanism 双锁机制。
//Lazy instantiation using double locking mechanism.
class Singleton
{
    private static Singleton instance;
    private Singleton()
    {
    System.out.println("Singleton(): Initializing Instance");
    }
    public static Singleton getInstance()
    {
        if (instance == null)
        {
            synchronized(Singleton.class)
            {
                if (instance == null)
                {
                    System.out.println("getInstance(): First time getInstance was invoked!");
                    instance = new Singleton();
                }
            }            
        }
        return instance;
    }
    public void doSomething()
    {
        System.out.println("doSomething(): Singleton does something!");
    }
}