设计模式之单例设计模式

程序在运行时候,通常会生成很多实例。但是我们想在程序中某个东西只存在一个时,就会有“只创建1个实例的需求”。像这样确保只生成一个实例的模式被称之为Singleton模式。即单例设计模式。这个模式必须保证2点。

1、确保任何情况下都绝对只有1个实例。

2、想在程序中表现出“只存在一个实例”。

接下来我们创建一个名字为Singleton的类。

package DesignPattern;
public class Singleton {
    private static Singleton singleton = new Singleton();
    private Singleton(){
        //在这里要将singleton的构造函数设置为private,这是为了,如果从这个类的外部我们调用这个类的构造函数(new Singleton())
        //的话就会报错,错误如下:Error:(6, 26) java: Singleton() 在 DesignPattern.Singleton 中是 private 访问控制
        //是给程序员不小心在此模式中用了new 类名()来创建实例的一个提醒,当然程序员可以用getInstance方法来获取实例
        //为了保证任何情况下都只能生成一个实例,我们将此构造方法设置为private。
        System.out.println("只生成了我这一个实例  实例1号");
    }
    public static Singleton getInstance(){
        return singleton;
    }
}
(new Singleton())
        //的话就会报错,错误如下:Error:(6, 26) java: Singleton() 在 DesignPattern.Singleton 中是 private 访问控制
        //是给程序员不小心在此模式中用了new 类名()来创建实例的一个提醒,当然程序员可以用getInstance方法来获取实例
        //为了保证任何情况下都只能生成一个实例,我们将此构造方法设置为private。
        System.out.println("只生成了我这一个实例  实例1号");
    }
    public static Singleton getInstance(){
        return singleton;
    }
}

接下来我们创建一个Main类,来测试。代码如下:

class Main{
    public static void main(String[] args) {
        System.out.println("程序开始运行");
        Singleton obj1 = Singleton.getInstance();
        Singleton obj2 = Singleton.getInstance();
        //调用getInstance来获取2个Singleton的实例
        //通过判断obj1和obj2是否相等来确认是否为同1个实例
        if (obj1==obj2){
            System.out.println("obj1和obj2是同一个实例");
        }else {
            System.out.println("obj1和obj2是不同的实例");
        }
        System.out.println("程序运行结束");
    }
}

代码运行的结果如下:

程序开始运行
只生成了我这一个实例  实例1号
obj1和obj2是同一个实例
程序运行结束

------------------------------------

我们发现,obj1和obj2其实是1个实例,这个实例就是在我们第一次调用getInstance方法时,Singleton类被初始化时,

 

 private static Singleton singleton = new Singleton();  //调用了私有的构造方法,打印 实例1号

static字段singleton被初始化,生成了一个唯一的实例!

单例设计模式使用注意2点:1、我们要定义获取实例的方法时,要设置为static,让它在类初始化时候,就只生成这1个实例

                                           2、为了防止不小心使用new 类名()方法创建实例,我们将构造函数设置成为了private。

 

我们在这里使用的是“饿汉式”,还有一种是“懒汉式”。
其实它们的总体模式都是一样的,“饿汉式”就是在第一张图片的第3行代码中,我们在创建这个类的具体实例的引用时候,就已经让它new了,指向了具体的对象,即图中的, private static Singleton singleton = new Singleton();。 
“懒汉式”的意思就是在第一个图中的第三行,我们这么写,private static Singleton singleton = null;不让它实例化,而是在调用获取它实例方法时候才,创建对象。再返回。 即在getInstance()方法里这么写:
public static Singleton getInstance(){

if(null==singleton){
 singleton = new Singleton(); // 没创建实例,引用为空时候,我们就创建,返回
}
return singleton ; 

}

它们的区别就是创建对象的时机不同!

补充:

静态内部类的单例设计模式写法:

/**
 * 单例模式  静态内部类版本
 * 因为在内部类加载和初始化时候,对象才被创建的。所以线程是安全的
 * 静态内部类是不会随着外部类的加载而初始化的,它需要单独初始化
 */
public class SingleTon {
    private SingleTon() {
    }

    private static class Inner{
        private static final SingleTon INSTANCE = new SingleTon();
    }

    public static SingleTon getInstance(){
        return Inner.INSTANCE;
    }
}

 

带同步代码块的线程安全的写法:

/**
 * *
 * 带同步代码块的 线程安全的版本、
 */
public class SingleTonThread {
    private SingleTonThread() {
    }
    private static SingleTonThread instance;
    public static SingleTonThread getInstance(){
        if (instance==null){
            synchronized (SingleTonThread.class){
                if (instance ==null){
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    instance = new SingleTonThread();
                }
            }
        }
        return instance;
    }
}

 

你可能感兴趣的:(读书笔记,设计模式)