[设计模式笔记] No.5 单件模式(singleton )

有一些对象其实我们只需要一个,比如:线程池、缓存、日志对象、注册表等。这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生,如资源使用过量、程序异常或者结果不一致等。

单件模式

确保一个类只有一个实例,并提供一个全局访问点。

①不考虑多线程并发的 单件模式实现
/**
 * 描述:不考虑多线程并发的单例实现
 * 程序狗: Xander
 * 创建日期: 2018/07/09 14:21
 */
public class Singleton {

    private static Singleton sInstance;

    private Singleton() {
    }

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

注意:上面的代码,如果使用多线程并发,仍然不能保证Singleton 类只有一个实例

②在方法 getInstance()上加上同步 synchronized,解决多线程并发问题,也就是说不会有两个线程可以同时进入这个方法。
public class Singleton {

    private static Singleton sInstance;

    private Singleton() {
    }

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

很明显,这样getInstance()能够正常工作,但是似乎同步 synchronized将会拖垮性能。因为同步一个方法可能造成程序执行效率降低100倍,因此,如果getInstance()的使用频繁运行,你可能就得要重新考虑了。

③使用“急切”创建实例,而不用延迟实例化的做法

如果应用程序总是创建并使用单件实例,或者在创建和运行方面的负担不太繁重,你可能想要急切创建此单件。

public class Singleton {

    private static Singleton sInstance = new Singleton();

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        return sInstance;
    }
}
④用“双重检查加锁”, 在getInstance()中减少使用同步。

重点: 利用“双重检查加锁”,首先检查是否实例已经创建,如果未创建,才进行同步。这样一来,只有第一次会同步,这正是我们想要到。

public class Singleton {

    private static Singleton sInstance;
    
    private Singleton() {
    }
    
    public static Singleton getInstance(){
        if(sInstance==null){
            synchronized(Singleton.class){
                if(sInstance==null) {
                    sInstance = new Singleton();
                }
            }
        }
        return sInstance;
    }
}

如果性能是你关心的重点,那么这个做法可以帮你大大地减少 getInstance() 的时间耗费。

要点
  • 单件模式确保程序中一个类只有一个实例。
  • 单件模式也提供访问这个实例的全局点。
  • 在Java中实现单例模式需要私有的构造器,一个静态方法和一个静态变量。
  • 确定在性能和资源上的限制,然后小心地选择适当的方案来实现单件,以解决多线程的问题(我们必须认定所有的程序都是多线程的)。
    感谢你的耐心阅读,单件模式基本知识和应用就介绍到这里了。

最后回顾一下

我们的设计工具箱中的工具
1、OO基础

① 抽象
② 封装
③ 多态
④ 继承

2、OO原则

① 封装变化
② 多用组合,少用继承
③ 针对接口编程,不针对实现编程
④ 为交互对象之间的松耦合设计而努力
⑤ 类应该对扩展开放,对修改关闭
⑥ 依赖抽象,不要依赖具体编程

3、OO模式

① 策略模式——定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

② 观察者模式——在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会受到通知并自动更新。

③ 装饰者模式——动态地将责任附加到对象上,若要扩展功能,装饰者提供有别于继承的另一种选择。

④ 工厂方法模式——定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂模式——提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

⑤单件模式——确保一个类只有一个实例,并提供全局访问点。

感谢阅读!
No.4 工厂模式(Factory)
No.3 装饰者模式(Decorator)
No.2 观察者模式(Observer)
No.1 策略模式(Strategy)
前言 为何要使用设计模式

Demo代码

你可能感兴趣的:([设计模式笔记] No.5 单件模式(singleton ))