您的位置:首页 > 其它

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

2016-03-27 16:28 330 查看

单例模式

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

结构图



保证三点:
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++中一般使用懒汉模式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: