设计模式2 单例模式

解决的问题

单例模式解决的问题就是:保证一个类只能实例化一个对象。

实现方法

一般我们保证一个类只有一个实例化对象时,做法是:


public class car{
    private Brake brake;
    public void useBreak(){
        if (brake == null)
            brake = new Brake();
        brake.run();
    }
}

如果这个brake对象不是仅供这一个Car类使用类呢?这样做只保证了在一个car对象有一个brake,多个car对象或者其他使用brake的类实例就会有多个brake出现了(当然这里的例子不好,本来就是一辆车子一个刹车)。所以我们不能把 保证只有一个实例的权利交给别人,应该让类自己来保证只实例化一个对象。
目前有这样几类方法:

懒汉法

懒汉法就是等到你需要一个单例实例的时候,我才会去实例化一个对象来给你。

public final class Singleton{
    private static Singleton singleton;
    
    private Singleton(){};
    
    public static Singleton getSingleton(){
        if (singleton == null)
            singleton = new Singleton();
        return singleton;
    }
}

饿汉法

饿汉法是先帮你实例化一个对象,你需要的时候就向我拿。饿汉法有如下几种实现方法:

下面这种方法是最简单也是最好理解的,但是在多线程的情况存在安全隐患。

    
public final class Singleton{

    private static Singleton singleton = new Singleton();
    
    private Singleton(){};
    
    public static Singleton getSingleton(){
        return singleton;
    }
}

下面这种方法利用了类在初始化时通过 方法按代码位置顺序执行类中静态成员变量的实例化和代码块的原理。类在实例化时通过 方法按代码位置先执行成员变量的实例化和代码块代码,在执行构造方法。而且 方法只会执行一次(在多线程的情况下也只会执行一次),所以在多线程情况下是安全的。


public final void Singleton{
    
    private static Singleton singleton;
    static{
        singleton = new Singleton();
    }
    private Singleton(){};
    
    public static Singleton getSingleton(){
        return singleton;
    }

}

下面这种方式是以enum(枚举)的方式实现,它是实现单例模式的最佳方式。这种实现方式在多线程,序列化情况下依旧是安全的。


public enum Singleton{
    SINGLETON;
    //  接下来就是定义变量和方法(值得注意的是:变量和方法最好不是静态,不然SINGLETON无法使用,只能通过Singleton使用静态变量和方法)
}

双检锁

双检锁是考虑到多线程的懒汉法。


public final class Singleton{
    
    private static Singleton singleton;
    
    private Singleton(){};
    
    private static Singleton getSingleton(){
        if (singleton == null){
            sychronized(Singleton.class){
                if (singleton == null)
                        singleton = new Singleton();
            }
            
        }
        return singleton;
    }
}

要点

  1. 保证单例的构造方法为private,这样就不能通过new来实例化单例(当然通过反射还是可以实例化多个对象)

  2. 保证单例是不能被继承的。

  3. 保证在获得单例实例的函数返回实例之前实例化实例。

这样实现的益处

  1. 控制资源的使用,通过线程同步来控制资源的并发访问

  2. 控制实例的产生,以达到节约资源的目的

  3. 控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信

猜你喜欢

转载自www.cnblogs.com/zhangchenwei/p/12409950.html