Java设计模式--单例模式

直想写点关于设计模式的东西,却懒到现在都没写过什么,今天上午看到项目中的代码,就在这个中午抽出时间写点东西,抛个项目截图先:

 

单例模式:

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

下面介绍Java中常用的单例模式:

一、懒汉模式

 

这种写法看上去似乎实现了单例模式,然鹅、实际应用中却不实用,尽管我所在的项目中有着类似的代码,我也不得不说确实如此;

优点:实现了按需创建,即懒加载

缺点:线程不安全。在多线程案例中,这种方式并没有完全实现单例模式。例如当多个线程访问getSingleton方法时,一起判断null == singleton,这时就会创建多个Singleton的实例。

实现了线程安全的懒汉模式(两种方式写法不同,却是一致的):

上面两种写法虽有差异,但运行效果却是相同的;

优点:解决了多线程的安全问题

缺点:效率却低的不要不要的。因为每当有线程访问时,就会出现线程排队等候,真正去创建实例的线程只有一个。

现实中也有人通过添加volatile关键字对对象实例进行限制,volatile保证其对所有线程的可见性,并且禁止对其进行指令重排序优化。

 下面介绍下兼顾线程安全与效率的懒汉模式:

这种方式被称为双重检查锁/双重校验锁方式,通过两次判null操作,它解决了线程安全的问题,不会创建多个实例。同时、也提高了线程访问的效率问题。这种方式可以算作是懒汉模式的最优解,但并非单例模式的最优解。

二、饿汉模式

 

优点:写法简单,一目了然

缺点:无法做到按需创建,即懒加载,增加负载。

注意:这里的增加负载要看具体情况,就上面的代码而言,new一个Singleton实例,算不上增加负载,但如果你new的是一个很大的对象,这时你应该考虑这个问题了。

三、静态内部类

把Singleton实例放到一个静态内部类中,这样就避免了静态实例在Singleton类加载的时候就创建对象,并且由于静态内部类只会被加载一次,所以这种写法也是线程安全的。

优点:线程安全,按需创建。

缺点:1、需要额外的工作(Serializable、transient、readResolve())来实现序列化,否则每次反序列化一个序列化的对象实例时都会创建一个新的实例。

   2、可能会有人使用反射强行调用我们的私有构造器(如果要避免这种情况,可以修改构造器,让它在创建第二个实例的时候抛异常)。

四、枚举

使用枚举除了线程安全和防止反射强行调用构造器之外,还提供了自动序列化机制,防止反序列化的时候创建新的对象。因此,Effective Java推荐尽可能地使用枚举来实现单例。

最后,不管采取何种方案,请时刻牢记单例的三大要点:

  • 线程安全
  • 延迟加载
  • 序列化与反序列化安全
原文地址:https://www.cnblogs.com/itachy/p/8287564.html