创建型模式(五):单例模式

1、模式的定义和特点

单例(Singleton)模式:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。它是最简单的设计模式之一。

特点:
1、单例类只能有一个实例
2、单例类必须自己创建自己的唯一实例
3、单例类对外提供一个访问该单例的全局访问点

缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

单例模式有多种写法,大部分都有以下关键代码(枚举写法除外):
1、私有的类类型变量
2、私有的构造方法
3、公共的获取实例的方法

2、模式的结构

主要角色:
单例类:包含一个实例且能自行创建这个实例的类。
访问类:使用单例的类。
在这里插入图片描述

图1-1 单例模式的结构图

3、模式的使用场景

1、某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
2、当对象需要被共享的场合。
由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
3、当某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。

4、单例模式的扩展

单例模式可扩展为有限的多例(Multitcm)模式,这种模式可生成有限个实例并保存在 ArrayList 中,客户需要时可随机获取,其结构图如图1-2所示。
在这里插入图片描述

图1-2 有限的多例模式的结构图

5、模式的实现

在这里插入图片描述

图1-3 示例代码结构图

5.1 懒汉式-线程不安全

单例类Singleton.java:

package com.example.designpattern.singleton;

class Singleton {
    /**
     * 1、懒汉式,线程不安全,不支持多线程,懒加载
     */
    private static Singleton instance;

    private Singleton (){}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

}

访问类Client.java:

package com.example.designpattern.singleton;

/**
 * @author Administrator
 * @date 2020/7/23
 * <p>
 * 经验之谈:
 * 1、一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第3种饿汉方式。
 * 2、只有在要明确实现lazy loading效果时,才会使用第5种登记方式。
 * 3、如果涉及到反序列化创建对象时,可以尝试使用第6种枚举方式。
 * 4、如果有其他特殊的需求,可以考虑使用第4种双检锁方式。
 */
class Client {
    public static void main(String[] args) {
        //1、懒汉式
        Singleton s1 = Singleton.getInstance();
        Singleton s11 = Singleton.getInstance();
        System.out.println(s1 == s11);

        //2、懒汉式,线程安全
        Singleton2 s2 = Singleton2.getInstance();
        Singleton2 s22 = Singleton2.getInstance();
        System.out.println(s2 == s22);

        //3、饿汉式
        Singleton3 s3 = Singleton3.getInstance();
        Singleton3 s33 = Singleton3.getInstance();
        System.out.println(s3 == s33);

        //4、双检索
        Singleton4 s4 = Singleton4.getInstance();
        Singleton4 s44 = Singleton4.getInstance();
        System.out.println(s4 == s44);

        //5、静态内部类
        Singleton5 s5 = Singleton5.getInstance();
        Singleton5 s55 = Singleton5.getInstance();
        System.out.println(s5 == s55);

        //6、枚举
        EnumSingleton e = EnumSingleton.INSTANCE;
        EnumSingleton ee = EnumSingleton.getInstance();
        System.out.println(e == ee);
    }
}

判断生成的实例是否一样,测试结果:
在这里插入图片描述

图1-4 测试结果

另外几种单例模式写法详见下列代码

5.2 懒汉式-线程安全

package com.example.designpattern.singleton;

class Singleton2 {
    /**
     * 2、懒汉式,线程安全,支持多线程,懒加载
     * 与方法1相比,使用了synchronized
     */
    private static Singleton2 instance;

    private Singleton2 (){}

    public static synchronized Singleton2 getInstance() {
        if (instance == null) {
            instance = new Singleton2();
        }
        return instance;
    }

}

5.3 饿汉式

package com.example.designpattern.singleton;

class Singleton3 {
    /**
     * 3、饿汉式,多线程安全,非懒加载
     */
    private static Singleton3 instance = new Singleton3();

    private Singleton3() {
    }

    public static Singleton3 getInstance() {
        return instance;
    }

}

5.4 双检锁

package com.example.designpattern.singleton;

class Singleton4 {
    /**
     * 4、双检锁/双重校验锁(DCL,即 double-checked locking)
     * 多线程安全,懒加载
     */
    private volatile static Singleton4 singleton;

    private Singleton4() {
    }

    public static Singleton4 getInstance() {
        if (singleton == null) {
            synchronized (Singleton4.class) {
                if (singleton == null) {
                    singleton = new Singleton4();
                }
            }
        }
        return singleton;
    }

}

5.5 静态内部类

package com.example.designpattern.singleton;

class Singleton5 {
    /**
     * 5、登记式/静态内部类
     * 多线程安全,懒加载
     */
    private static class Inner {
        private static final Singleton5 INSTANCE = new Singleton5();
    }

    private Singleton5() {
    }

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

}

5.6 枚举

package com.example.designpattern.singleton;

/**
 * 6、枚举
 * JDK1.5起,多线程安全,非懒加载
 * 实现单例模式的最佳方法
 */
enum EnumSingleton {
    /**
     * 枚举值
     */
    INSTANCE;

    //doSomething 该实例支持的行为

    /**
     * 可以省略此方法,通过EnumSingleton.INSTANCE进行操作
     */
    public static EnumSingleton getInstance() {
        return EnumSingleton.INSTANCE;
    }

}

6、PPT素材

在这里插入图片描述

PPT 01

在这里插入图片描述

PPT 02

在这里插入图片描述

PPT 03

在这里插入图片描述

PPT 04

在这里插入图片描述

PPT 05

在这里插入图片描述

PPT 06

在这里插入图片描述

PPT 07

在这里插入图片描述

PPT 08

微信公众号: TechU
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值