[size=large] [color=red]深入探究设计模式<二>——Singleton单例模式[/color][/size]
一、功能与结构
A.定义 单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点 。
B.用途 此模式用在要求只能出现一个类的实列的某个项目中。比如:项目的全局配置信息、Factory、主控类等。
C.结构图
[img]http://dl.iteye.com/upload/attachment/0064/6147/95473378-ebdc-3ab6-b5df-b2189ef085a9.jpg[/img]
单例设计模式是我们讨论和使用比较广泛的一种设计模式。
二、模式剖析
我的示例代码
示例分析
A.关键点分析 首先我明确我们的工作是什么?我们要尽全力保证我们所定义的类一定只能在自己的内部创建和只能实例化一次!!这是十分重要的。
关键点1:定义类的构造方法的修饰符为private(私有)。
这里是排除子类造成会实例化多个对象的可能。保证了继承性。
关键点2:示例代码中
虽然保证了只会实例化一个对象,但是可能会造成多个线程读取操作,避免不必要的CPU资源浪费。
B.分析与评估
上面的示例代码已能满足觉大部分应用场合情况的要求了。额外情况考虑
JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader)。可能出现JVM 多个ClassLoader加载了相同实例对象的情况 。即ClassLoader (bootstrap)A 加载a1(Singleton a1 = new Singleton()),ClassLoader (user-defined class loader)B加载a2(Singleton a2 = new Singleton())
逻辑上讲a1=a2,但是由于a1和a2来自于不同的ClassLoader,它们实际上是完全不同的,如果A中定义了一个静态变量c,则c在不同的ClassLoader中的值是不同的。
序例化 如果我们的这个Singleton类是一个关于我们程序配置信息的类。我们需要它有序列化的功能,那么,当反序列化的时候,我们将无法控制别人不多次反序列化。
处理方法:我们可以利用一下Serializable接口的readResolve()方法,比如:
一、功能与结构
A.定义 单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点 。
B.用途 此模式用在要求只能出现一个类的实列的某个项目中。比如:项目的全局配置信息、Factory、主控类等。
C.结构图
[img]http://dl.iteye.com/upload/attachment/0064/6147/95473378-ebdc-3ab6-b5df-b2189ef085a9.jpg[/img]
单例设计模式是我们讨论和使用比较广泛的一种设计模式。
二、模式剖析
我的示例代码
package SingletonPattern;
/**
* 单例对象 ver 1.0
* @author DeopingXiong
*
*/
public class Singleton {
//定义将要取得类的实现对象,并赋值为空。
private static Singleton singleton = null;
//因只需要在内部实例化对象,所以定义为了私有属性
private Singleton(){
}
//定义获取实列的方法
public static Singleton getInstance(){
if(singleton==null){//如果实例已经创建了,就不需要同步,直接返回,否则就同步线程
synchronized(Singleton.class){
if(singleton==null){//如果被同步的线程中,有一个线程创建了对象,那么别的线程就不再创建实列对象。
singleton = new Singleton();//实列化对象
}
}
}
return singleton;
}
}
示例分析
A.关键点分析 首先我明确我们的工作是什么?我们要尽全力保证我们所定义的类一定只能在自己的内部创建和只能实例化一次!!这是十分重要的。
关键点1:定义类的构造方法的修饰符为private(私有)。
这里是排除子类造成会实例化多个对象的可能。保证了继承性。
关键点2:示例代码中
getSingleton()
方法中第一个
if(singleton==null)
判定。排除了被多个线程调用getSingleton()创建多个实例对象,造成内存泄漏的问题。
getSingleton()
方法中第二个
if(singleton==null)
虽然保证了只会实例化一个对象,但是可能会造成多个线程读取操作,避免不必要的CPU资源浪费。
B.分析与评估
上面的示例代码已能满足觉大部分应用场合情况的要求了。额外情况考虑
JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader)。可能出现JVM 多个ClassLoader加载了相同实例对象的情况 。即ClassLoader (bootstrap)A 加载a1(Singleton a1 = new Singleton()),ClassLoader (user-defined class loader)B加载a2(Singleton a2 = new Singleton())
逻辑上讲a1=a2,但是由于a1和a2来自于不同的ClassLoader,它们实际上是完全不同的,如果A中定义了一个静态变量c,则c在不同的ClassLoader中的值是不同的。
序例化 如果我们的这个Singleton类是一个关于我们程序配置信息的类。我们需要它有序列化的功能,那么,当反序列化的时候,我们将无法控制别人不多次反序列化。
处理方法:我们可以利用一下Serializable接口的readResolve()方法,比如:
public class Singleton implements Serializable
{
......
......
protected Object readResolve()
{
return getInstance();
}
}