研磨设计模式学习笔记之单例模式

来源:互联网 发布:澳门十月初五饼家淘宝 编辑:程序博客网 时间:2024/04/30 05:18

1、单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点 。   

2、单例模式结构及说明:Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,让外部来访问这个类的唯一实例。 

3、单例模式示例代码:

  3.1 单例模式又分为饿汉式与懒汉式单例模式。

        饿与懒的区别,饿表示的是在程序加载的时候即创建一个静态实例。懒顾名思义即当在需要他的时候才会创建。

  3.2 恶汉式代码:

     

package singleton;/** * 懒汉式单例模式 * @author Administrator * */public class SingletonSample2 {/** * 定义一个变量来存储创建好的类的实例 */private static SingletonSample2 uniqueInstance= null;/** * 私有构造方法,可以在内部控制创建实例的数目 */private SingletonSample2(){}/** * 定义一个方法来为客户端提供实例 * @return */public static synchronized SingletonSample2 getInstance(){//判断存储实例的变量是否有值if(null == uniqueInstance){//如果没有,就创建一个类实例,并把值赋给存储类实例的变量uniqueInstance = new SingletonSample2();}//有值就直接返回return uniqueInstance;}/** * 定义自己的方法 */public void singletonOperation(){}/** * 定义自己的属性 */private String singletonData;public String getSingletonData() {return singletonData;}public void setSingletonData(String singletonData) {this.singletonData = singletonData;}}
测试类
public class SingletonTest {public static void main(String[] args) {SingletonSample2 s21 = SingletonSample2.getInstance();SingletonSample2 s22 = SingletonSample2.getInstance();System.out.println(s21==s22);}}
测试结果:返回true


  3.2 懒汉式代码:

package singleton;/** * 恶汉式单例模式 * @author Administrator * */public class SingletonSample1 {/** * 定义一个变量来存储创建好的类的实例,直接在这里创建类的实例,只能创建一次 */private  static  SingletonSample1 uniqueInstance= new SingletonSample1();/** * 私有构造方法,可以在内部控制创建实例的数目 */private SingletonSample1(){}/** * 定义一个方法来为客户端提供实例 * @return */public static SingletonSample1 getInstance(){return uniqueInstance;}/** * 定义自己的方法 */public void singletonOperation(){}/** * 定义自己的属性 */private String singletonData;public String getSingletonData() {return singletonData;}public void setSingletonData(String singletonData) {this.singletonData = singletonData;}}

4、单例模式线程安全性:不加同步的懒汉式是线程不安全的,在多线程的环境中可能会导致并发问题。而饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候不会发生并发的。

  4.1 如何实现懒汉式线程安全呢? 当然可以直接在getInstance()方法上加上synchronized关键字。但这样就会降低整个访问的速度,而且每次都要判断。故出现了双重检查加锁。

  4.2 双重检查加锁机制:指的是并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在如果不存在,就在同步块的情况下创建一个实例,这就是第二重检查。这样一来,就只需要同步一次了。从而减少了多次在同步的情况下进行的判断而浪费的时间。 不多说,上代码。

package singleton;/** * 双重检查加锁懒汉式单例模式 * @author Administrator * */public class SingletonSample3 {/** * 定义一个变量来存储创建好的类的实例需添加volatile修饰 */private volatile static SingletonSample3 uniqueInstance= null;/** * 私有构造方法,可以在内部控制创建实例的数目 */private SingletonSample3(){}/** * 定义一个方法来为客户端提供实例 * @return */public static SingletonSample3 getInstance(){//判断存储实例的变量是否有值if(null == uniqueInstance){//同步块,线程安全地创建实例synchronized (SingletonSample3.class) {//再次检查实例是否存在,如果不存在才真正的创建实例if(null == uniqueInstance){uniqueInstance = new SingletonSample3();}}}//有值就直接返回return uniqueInstance;}/** * 定义自己的方法 */public void singletonOperation(){}/** * 定义自己的属性 */private String singletonData;public String getSingletonData() {return singletonData;}public void setSingletonData(String singletonData) {this.singletonData = singletonData;}}
(建议双重检查加锁用在java5及以上版本。)

5、单例模式的更好实现方式:类级内部类。

  5.1 类级内部类:有static修饰的成员式内部类。如果没有static修饰的成员内部类被称为对象内部类。

  5.2 多线程缺省同步锁。

         在多线程开发中,为了解决并发问题,主要是通过使用synchronized来加互斥锁进行同步控制。但是某些情况中,虚拟机已经隐含地为您执行了同步,这些情况就不用直接再来进行同步控制了。这些情况包括:

  • 由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时
  • 访问final字段时
  • 在创建线程之间创建对象
  • 线程可以看见它要处理的对象时

   5.3 更为简单的实现单例模式实例代码

package singleton;/** * 双重检查加锁懒汉式单例模式 * @author Administrator * */public class SingletonSample4 {/** * 类级内部类 * 没有绑定关系,而且只有在调用的时候才会加载,从而实现了延迟加载 */private static class SingletonHolder{/** * 静态初始化器,由JVM来保证线程安全 */private static SingletonSample4 instance = new SingletonSample4();}public static SingletonSample4 getInstance(){return SingletonHolder.instance;}/** * 私有构造方法 */private SingletonSample4(){}/** * 定义自己的方法 */public void singletonOperation(){}/** * 定义自己的属性 */private String singletonData;public String getSingletonData() {return singletonData;}public void setSingletonData(String singletonData) {this.singletonData = singletonData;}}
6、还有种更为简洁,高效,安全的实现单例方法---通过枚举来显示单例模式。

package singleton;public enum SingletonSample5 {/** * 定义一个枚举元素,它就代表了Singleton的一个实例 */uniqueInstance;/** * 自定义方法 */public void singletonOperation(){}}

以上是单例的模式的几种不同的实现方式,与大家一同学习。


Little progress every day!











原创粉丝点击