面向对象设计模式:创建型模式之单例模式

1. 单例模式,Singleton Pattern

1.1 Definition 定义

单例模式是确保类有且仅有一个实例的创建型模式,其提供了获取类唯一实例(全局指针)的方法。
单例模式类提供了一种访问其唯一的对象的方式,可以直接访问,而不需要实例化该类的对象。

1.2 Motivation 动机

Sometimes we want just a single instance of a class to exist in the system. For example, we want just one window manager, or just one factory for a family of products.
有时我们只希望系统中存在一个类的单个实例。例如,我们只需要一个窗口管理器,或者一个产品系列只需要一个工厂。

1.3 Benefit 益处
  • Controlled access to sole instance. 对唯一实例的受控访问
  • More flexible than static class (class with all static properties and methods). 比静态类灵活
    • Static class must be stateless; Singleton could be stateful. 静态类必须无状态,单例可以有状态
1.4 实现
  • 私有构造方法
  • 获取唯一实例引用的静态方法

2. 单例模式类型

2.1 懒汉式-线程不安全
  • 懒加载:是
  • 线程安全:否
public class LazyLoadingSingleton {
    private static LazyLoadingSingleton lazyLoadingSingleton;

    private LazyLoadingSingleton() {

    }

    public static LazyLoadingSingleton singleton() {
        if (lazyLoadingSingleton == null) {
            lazyLoadingSingleton = new LazyLoadingSingleton();
        }
        return lazyLoadingSingleton;
    }

    public void log(String msg) {
        System.out.println("Log: " + msg);
    }
}
2.2 懒汉式-线程安全
  • 懒加载:是
  • 线程安全:是
  • 优点:首次调用初始化,避免内存占用
  • 缺点:影响效率
public class LazyLoadingSingleton {
    private static LazyLoadingSingleton singleton;

    private LazyLoadingSingleton() {

    }

    public static synchronized LazyLoadingSingleton singleton() {
        if (singleton == null) {
            singleton = new LazyLoadingSingleton();
        }
        return singleton;
    }

    public void log(String msg) {
        System.out.println("Log: " + msg);
    }
}

2.3 饿汉式

建议采用

  • 懒加载:否
  • 线程安全:是
  • 优点:未加锁,效率高
  • 缺点:类加载时初始化,浪费内容
public class ClassLoadSingleton {
    private static ClassLoadSingleton singleton = new ClassLoadSingleton();

    private ClassLoadSingleton() {

    }

    public static ClassLoadSingleton singleton() {
        return singleton;
    }

    public void log(String msg) {
        System.out.println("Log: " + msg);
    }
}

解法:静态内部类,延迟类加载的对象实例化

public class ClassLoadSingleton {
    // private static ClassLoadSingleton singleton = new ClassLoadSingleton();

    private static class SingleHandler {
        private static final ClassLoadSingleton singleton = new ClassLoadSingleton();
    }

    private ClassLoadSingleton() {

    }

    public static ClassLoadSingleton singleton() {
        return SingleHandler.singleton;
    }

    public void log(String msg) {
        System.out.println("Log: " + msg);
    }
}

2.4 双重校验锁:校验是否为空

双次校验是否为空,类加锁在双次校验之中
可以使用

  • 懒加载:是
  • 线程安全:是
  • 优点:保证多线程下的效率
package singleton;

public class DoubleCheckSingleton {
	private volatile static DoubleCheckSingleton singleton;
    
    private DoubleCheckSingleton() {

    }

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

    public void log(String msg) {
        System.out.println("Log: " + msg);
    }
}

关于 volatile 易失性关键字:
volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值(在某一线程写入寄存器但且未写入变量地址),如果这个变量由别的程序更新了的话,将出现不一致的现象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值