设计模式学习笔记——单例模式

来源:互联网 发布:sql server 百度网盘 编辑:程序博客网 时间:2024/05/01 10:30

单例模式

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

结构图


保证三点:
1.私有的构造方法,防止从类的外部实例化。
2.指向自己实例的私有静态引用。
3.以自己实例为返回值的静态的公有的方法。

饿汉单例

饿汉单例,在单例类加载的时候,实例化一个对象交给引用。

代码实现

/** * 饿汉单例:在类加载的时候,实例化一个对象交给自己的引用 * * @author xukai 2016年3月27日 下午2:49:12 *  */public class Singleton {// 加载时实例化private static Singleton singleton = new Singleton();/** * 私有的构造方法,除反射和克隆无法重新实例化 */private Singleton() {}/** * 返回实例对象 */public static Singleton getInstance() {return singleton;}}

懒汉单例

懒汉单例,调用获取单例的实例方法时,实例化对象。(线程安全)

代码实现

/** * 懒汉单例:调用获取实例方法时,实例化对象 * * @author xukai 2016年3月27日 下午2:52:40 *  */public class Singleton {private static Singleton singleton = null;/** * 私有的构造方法,除反射无法重新实例化 */private Singleton() {}/** * synchronized对方法加锁,同步 */public static synchronized Singleton getInstance(){if(singleton == null)// 1{singleton = new Singleton();//2}return singleton;}}
在Java多线程中,当第一次调用getInstance方法时,需要同步(synchronized),非第一次调用此方法都需要付出同步代价,太消耗资源,下面有双重检查锁解决此问题。

双重检查锁

/** * 双重检查锁 * * @author xukai 2016年3月27日 下午3:42:00 *  */public class Singleton {private static Singleton singleton = null;/** * 私有的构造方法,除反射无法重新实例化 */private Singleton() {}public static Singleton getInstance() {if (singleton == null) // 1{// 对类进行加锁,当前对象只能被一个对象调用或拥有synchronized (Singleton.class) // 2{if (singleton == null) // 3{singleton = new Singleton();}}}return singleton;}}
由于懒汉模式非第一次调用获取实例方法都要付出同步的代价,这种代价太高。而双重检查锁是在判断之后进行有选择的加锁。
双重检查锁:
1.进入getInstance,singleton引用对象为空
2.对类进行加锁,防止此时有多个线程都是访问。
3.再次判断此时singleton是否为空。
4.实例化对象。
这里的第三步是为了防止出现这种情况:线程1和线程2同时进入getInstance方法中,假如线程1先获得了当前对象锁,并执行了下面的操作,实例化对象,将锁释放,此时线程2处于代码中的2位置,继续执行,获得当前类的锁,实际上线程1已经实例化出一个对象了,假如代码中的位置3没有添加空判断,那么会重新实例一个新的对象。

单例模式优点

1.在内存中只有一个对象,节省内存空间。
2.避免频繁的创建销毁对象,可以提高性能。
3.避免对共享资源的多重占用。
4.可以全局访问。

使用场景

1.需要频繁实例化然后销毁对象。
2.创建对象时过多或者消耗资源过多,经常使用。
3.有状态的工具类对象。
4.频繁访问数据库或文件的对象。

注意

1.不要使用反射,否则会实例化一个新对象。
2.不要断开单例类对象和它的静态引用。
3.多线程使用共享资源,注意线程安全。

Java中,优先使用饿汉模式。C++中一般使用懒汉模式。
1 0
原创粉丝点击