第21章《单例模式》

今天买了《大话设计模式》这本书,也是找朋友推荐的。晚上拿到手,就看了一下单例模式这一章,因为自己只是知道单例模式,其它模式完全不懂,就想看看这本书是不是真的读起来容易理解以及讲的怎么样。一个小时看完这一章节,觉得还可以吧,讲的东西是很容易理解,且循序渐进,虽然讲的东西自己基本都是知道的,因为之前就了解这个模式。接下来还要把其它模式研究一下,继续努力~~~


关于单例模式,补充一下自己曾经遗漏的知识点:

1、单例模式不仅仅要保证一个类在内存中只存在一个实例,而且提供一个它的全局访问点(而且这里是之前自己模糊的地方)。


2、如何保证一个类的全局实例变量不被实例化多次?

    最好的方式就是:让类自身来保存它的唯一实例 。

    这个类可以保证以下两点:(1)这个全局实例变量只被实例化一次。

                                               (2)提供一个访问这个全局实例变量的public方法。


3、单例  VS  实用类的静态方法

相同点:实用类也经常使用private的实例构造器方法,从而避免创建其它类创建它的实例。

不同点:(1)实例类不保存状态,比如,你不会去判断它是否为null,然后再去调用它的方法;但是单例是有状态的,单例的创建过程就是先判断是否为null,然后才确定要不要创建它的实例。

(2)实用类不能被继承(你没见过有类继承Math类吧,因为它是final类型的);单例类可以被子类继承。

(3)实用类仅仅是一些方法、属性的集合;单例有自己的对象实例。


4、单例的初始化时间

根据单例的初始化时间,单例类可以被饿汉式单例类和懒汉式单例类。

4.1、饿汉式单例类:在类初始化式,分配内存;

4.1.1、这可以通过两种方式实现:

         4.1.1、静态初始化。从JVM角度分析,就是在执行静态代码时,被初始化。

         4.1.2、构造器方式。这需要将作为实例变量单例的实例化代码写在类的构造函数里面。也就是在执行完类的静态代码后,再执行类的构造器函数时,创建单例实例。

         4.1.3、缺点:会提前占用内存。通过静态初始化方式,在类未被实例化时,就为单例分配内存空间。通过构造器方式,在类实例化时,为单例分配内存空间。

懒汉式单例类:

4.2.1、懒汉式单例类:在单例被第一次调用时,分配内存;


5、测试code:

5.1、懒汉式1

/**version1 未考虑多线程安全问题  && 懒汉式
**/

class  SingleTon{
    private static SingleTon singleTon=null;
    private SingleTon(){}
    public static SingleTon getSingleTon(){
        if(singleTon==null){
            singleTon=new SingleTon();
        }
        return singleTon;
    }
}
public class Main{
    public static void main(String[] args) throws Exception {
        SingleTon s1=SingleTon.getSingleTon();
        SingleTon s2=SingleTon.getSingleTon();
        System.out.println(s1==s2);//true,说明二者内存地址相同,所以二者肯定是同一个对象,所以保证了类的单例存在
    }
}

5.2、懒汉式2

/**version2 考虑多线程安全问题 && 懒汉式
**/

class  SingleTon{
    private static SingleTon singleTon=null;

    private SingleTon(){}
    synchronized public static SingleTon getSingleTon(){
        if(singleTon==null){
            singleTon=new SingleTon();
        }
        return singleTon;
    }
}
public class Main{
    public static void main(String[] args) throws Exception {
        SingleTon s1=SingleTon.getSingleTon();
        SingleTon s2=SingleTon.getSingleTon();
        System.out.println(s1==s2);//true,说明二者内存地址相同,所以二者肯定是同一个对象,所以保证了类的单例存在
    }
}

5.3、饿汉式(4.1.1)

/**version3  饿汉式(类构造器clinit()初始化时,分配内存)
**/

class  SingleTon{
    private static SingleTon singleTon=new SingleTon();
    private SingleTon(){}
    public static SingleTon getSingleTon(){
       return singleTon;
    }
}
public class Main{
    public static void main(String[] args) throws Exception {
        SingleTon s1=SingleTon.getSingleTon();
        SingleTon s2=SingleTon.getSingleTon();
        System.out.println(s1==s2);//true,说明二者内存地址相同,所以二者肯定是同一个对象,所以保证了类的单例存在
    }
}

5.4、饿汉式(4.1.2)

/**version4 饿汉式(实例构造器初始化时,分配内存)
**/

class  SingleTon{
    private static SingleTon singleTon=null;
    private SingleTon(){
        singleTon=new SingleTon();
    }
    public static SingleTon getSingleTon(){
       return singleTon;
    }
}
public class Main{
    public static void main(String[] args) throws Exception {
        SingleTon s1=SingleTon.getSingleTon();
        SingleTon s2=SingleTon.getSingleTon();
        System.out.println(s1==s2);//true,说明二者内存地址相同,所以二者肯定是同一个对象,所以保证了类的单例存在
    }
}


参考资料:《大话设计模式》程杰  p209-p219


你可能感兴趣的:(大话设计模式笔记)