[23种设计模式][创建型]14.单例模式

211 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

1.意图:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2.适用性:

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

3.单例(Singleton)模式构成:

单例(Singleton):提供一个 getInstance() 方法,让客户可以使用它的唯一实例,其内部实现只生成一个实例(该类的实例是在类内部生成的)。单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。

4.通常单例模式在Java语言中,有两种构建方式:

  • 懒汉方式。指全局的单例实例在第一次被使用时构建。
  • 饿汉方式。指全局的单例实例在类装载时构建。

5.单例模式UML类图:

Image.png

6.单例模式UML时序图:

Image.png

7.代码示例:

Image.png

单例:

public class Signleton {

    // 实现方式一(饿汉式)
//    private static Signleton signleton = new Signleton();

    // 实现方式二(懒汉式)
    private static Signleton signleton;

    private Signleton() {

    }

    /* // 实现方式一(饿汉式)
    public static Signleton getInstance() {
        return signleton;
    }
    */

    // 实现方式二(懒汉式)再多线程中会出现多个线程同时进入if判断。
    public static Signleton getInstance() {

        if (null == signleton) {
            signleton = new Signleton();
        }

        return signleton;
    }
}

客户角色:

public class Client {

    public static void main(String[] args) {

        Signleton s1 = Signleton.getInstance();
        Signleton s2 = Signleton.getInstance();

        System.out.println(s1 == s2);
    }
}