创建型设计模式之单例模式

155 阅读3分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

单例模式:(Singleton)

  单例的有且只有一个实例对象

要点:

创建-构造器私有

可以外部访问

静态;

image.png

我自己写的是这样的:


/**
 * @author Lucas
 * @create 2021-08-10 15:01
 * @description  单例模式的实体类
 */
public class Person {


    private String name;

    private  Integer age;
    /**
     * 单例模式;要求此系统中有且只有一个实例对象;
     *
     *  1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
     *  2.构造器私有化
     *  3.外部访问对象,要从我们自己构造好的私有对象返回       *
     */


 
    /**
     * 1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
     * private  static final  Person Instanc=new Peson(); 饿汉式,不让变动
     */
    private  static   Person Instance;   //懒汉式时间换空间



    /**
     * 2.构造器私有化
     */
    private Person (){
        System.out.println("需要创建一个对象person");
    }

    /**3.外部访问
     * 公共的静态方法-->利用静态存储方法区,
     * 建立一个静态的空对象,如果需要就一直存在,直至程序完结
     * @return
     */
    public static Person getPerson(){
        //多线程情况下不安全
        if (Instance==null){
            Person person=new Person();
            Instance=person;
        }
    return Instance;
    }

    public static void main(String[] args) {
       //静态的公共获取方法--对象都一样
        Person person1 = Person.getPerson();
        Person person2 = Person.getPerson();

        System.out.println(person1==person2);
    }
}

上述的情况在于多线程的是不安全的; 如何优化呢

image.png

     * 公共的静态方法-->利用静态存储方法区,
     * 建立一个静态的空对象,如果需要就一直存在,直至程序完结
     * @return
     */
    public static synchronized Person getPerson(){
        //多线程情况下不安全
        if (Instance==null){
            Person person=new Person();
            Instance=person;
        }
    return Instance;
    }

优化二:

image.png


/**
 * @author  Lucas
 * @create 2021-08-10 15:16
 * @description  单例模式的实体类
 */
public class Person {


    private String name;

    private  Integer age;
    /**
     * 单例模式;要求此系统中有且只有一个实例对象;
     *
     *  1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
     *  2.构造器私有化
     *  3.外部访问对象,要从我们自己构造好的私有对象返回       *
     */



    /**
     * 1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
     * private  static final  Person Instanc=new Peson(); 饿汉式,不让变动
     */
    private  static  volatile Person Instance;



    /**
     * 2.构造器私有化
     */
    private Person (){
        System.out.println("需要创建一个对象person");
    }

    /**3.外部访问
     * 公共的静态方法-->利用静态存储方法区,
     * 建立一个静态的空对象,如果需要就一直存在,直至程序完结
     * @return
     */
    public static  Person getPerson(){
        //多线程情况下不安全
        if (Instance==null){
            synchronized (Person.class){
                //同步代码块+双重检查锁(+ volatile内存可见性,创建对象防止指令重排序)
                if (Instance==null){
                Person person=new Person();
                Instance=person;
            }}

        }
    return Instance;
    }

    public static void main(String[] args) {
       //静态的公共获取方法--对象都一样
        Person person1 = Person.getPerson();
        Person person2 = Person.getPerson();

        System.out.println(person1==person2);
    }
}

本质上: 对于单列模式:基本是双重锁+内存可见性

2.2.单例模式的适用场景:

系统信息,环境变量的基础信息:

image.png