设计模式之——单例模式

今天早上坐地铁,顺便浏览了一下设计模式之禅
该书通俗易懂,基于该书来聊聊设计模式之单例模式
以后可能也会基于该书写

聊聊皇帝

众所周知,一山不容二虎,一国不容两帝,古代的王朝老大只有一个;
谈到皇帝大家都会知道皇帝是谁,这一个过程反应的设计领域就是,要求一个类只能生成一个对象(皇帝),所有对象对他的依赖是相同的,大家和皇帝建立稳固的联系,我们把这种职业通过程序来实现。

皇帝只能有一个,也就是一个类只能产生一个对象,如何实现?
对象通常是通过new关键字产生的,调用相应的构造器产生一个新的对象,那么我们要阻止别人生成新对象就需要将构造器私有化。
来看看皇帝类代码:

public class Emperor {
    private static final Emperor EMPEROR = new Emperor();

    private Emperor(){}

    public static Emperor getInstance() {
        return EMPEROR;
    }
}

私有化构造器避免了其他类new对象,需要访问皇帝可以通过getInstance获取。

单例模式定义

确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式的通用类图:
单例模式
Singleton类称为单例类,通过使用private的构造函数确保应用只有一个实例。

单例模式优点

  • 由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁的创建、销毁时,而且创建或销毁的性能无法优化,单例模式的优势就非常明显,Spring中就有大量的单例。
  • 由于单例模式开销小,当一个对象产生比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过启动时产生一个单例对象永久驻留内存的方式来解决
  • 单例模式避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件同时写操作。
  • 单例模式可以在系统设置全局的访问优点,优化共享资源的访问,例如可以设计一个单例类,负责所有数据表的映射。

单例模式的缺点

  • 单例模式一般没有接口,扩展困难,若要扩展,除了修改代码基本没有第二种途径可以实现。单例模式为什么不能增加接口呢?因为接口对单例模式没有任何意义,它要求自行实例化并提供单一实例,接口或抽象类是不可被实例化的。
  • 单例模式对测试是不利的,在并行开发环境中,如果单例模式没有完成,是不能进行测试的,没有接口也不能使用mock的方式虚拟一个对象。

单例模式使用场景

在一个系统中,要求一个类有且仅有一个对象,可以采用。如:

  • 要求生成唯一序列号的环境
  • 在整个项目中需要共享访问点或共享数据
  • 创建一个对象需要消耗的资源过多,要访问io、数据库等资源
  • 需要定义大量静态常量和静态方法(如工具类),当然也可以使用static的方式

单例模式的注意事项

在高并发情况下,需要注意单例模式的线程同步问题。上面的例子不会产生多个实例,但是如下单例模式代码需要考虑线程同步:

public class Singleton {
    private static final Singleton SINGLETON = null;

    private Singleton(){}

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

该模式在单线程情况下尚不会出现问题,但是多线程并发下就会破坏单例。解决的办法有很多,可以在getInstance方法加synchronized,也可在方法内部加synchronized来实现。当然如果非要杠的话,利用反射或复制对象也可以破坏单例模式。

最佳实践

单例模式是23个模式中比较简单的模式,应用也很广泛,在spring中,每个bean默认是单例的,这样的优点是Spring容器可以管理这些bean的生命周期,决定何时创建和销毁。

参考:《设计模式之禅》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值