读书人

设计形式-创建模式-单例模式-java

发布时间: 2013-01-19 11:41:36 作者: rapoo

设计模式--创建模式--单例模式--java
Intent:

?Ensurea class only has one instance, and provide a global point of access to it.

确保一个类只有一个实例,并且提供一个全局的引用来获取它。

Applicability ?theremust be exactly one instance of a class, and it must be accessible to clientsfrom a well-known access point. ?仅有一个实例,并且客户端需要从一个众所周知的访问点来获取它。 ?whenthe sole instance should be extensible bysubclassing, and clients should be able to use an extended instancewithout modifying their code. ?当这个唯一实例应该通过子类化可扩展的,并且客户端应该无需更改代码就能使用一个扩展的实例时。Consequences ?Controlled access to sole instance ?控制实例访问 ?Reduced name space ?减少名空间 ?Permits refinement of operations and representation ?允许对操作和表示的精化 ?Permits a variable number of instances ?允许可变数数目的实例 ?More flexible than class operations ?比类操作更灵活UML设计形式-创建模式-单例模式-javaCode 饿汉方式实现。当隐式加载Singleton,变初始化singleton。
/** * 饿汉 *  * @author changsheng */public class Singleton {static private final Singleton singleton = new Singleton();private Singleton(){}static public Singleton getInstance() {return singleton;}}
利用反射破坏单例
@SuppressWarnings("unchecked")public static void reflect() throws InstantiationException,IllegalAccessException, InvocationTargetException {Class<Singleton> clazz = Singleton.class;/* get constructors info */Constructor<?>[] methods = (Constructor<Singleton>[]) clazz.getDeclaredConstructors();for (int i = 0; i < methods.length; i++) {System.out.println(methods[i]);}methods[0].setAccessible(true);Singleton s1 = (Singleton) methods[0].newInstance();Singleton s2 = (Singleton) methods[0].newInstance();System.out.println(s1 == s2);}

懒汉实现。当显式调用Singleton2.getInstance才初始化singleton2.
/** * 懒汉 * @author changsheng * */public class Singleton2 {static private Singleton2 singleton2;private Singleton2(){}        //sychronized关键字不是必须的,根据需求而定。static synchronized public Singleton2 getInstance(){if(singleton2 == null){singleton2 = new Singleton2();}return singleton2;}}


懒汉和饿汉的选择主要以单例实例化是否耗时为衡量标准。

双重检查机制,主要解决多线程并发访问的效率。具体并发知识可查阅书籍Java Concurrency in practice。

class Singleton3 {static volatile private Singleton3 singleton3;/*此处为什么要使用volatile关键字?一旦线程改变了singleton3,其他线程可立即可见*/private Singleton3(){}/** * 为什么要使用双重检查机制?避免多个线程排队问题 */static public Singleton3 getInstance(){if(singleton3 == null){synchronized (Singleton3.class) {if(singleton3 == null)singleton3 = new Singleton3();}}return singleton3;}}

通过序列化来破坏单例。
public class Singleton3 implements Serializable {private static final long serialVersionUID = 1L;static private final Singleton3 s = new Singleton3();private Singleton3(){}static public Singleton3 getInstance(){return s;}public static void main(String[] args) throws IOException, ClassNotFoundException {Singleton3 s1 = Singleton3.getInstance();Singleton3 s2 = Singleton3.getInstance();System.out.println(s1 == s2);ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(s1);ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream  ois = new ObjectInputStream(bis);Singleton3 s3 = (Singleton3) ois.readObject();System.out.println(s1 == s3);}}

java中实现单例最佳方式。具体细节查阅thinking in java
public enum Singleton {Instance;static public Singleton getInstance(){return Instance;}public int method1(){return 1;}public int method2(){return 2;}}


可拓展的单例。
/** *  * @author changsheng */public class SingletonExtends {static private final SingletonExtends singleton = new SingletonExtends();protected SingletonExtends(){}static public SingletonExtends getInstance() {return singleton;}public void method(){}}


public class SingletonExtendsEx extends SingletonExtends {static private final SingletonExtendsEx singleton = new SingletonExtendsEx();static public SingletonExtendsEx getInstance() {return singleton;}private SingletonExtendsEx() {super();}public void method1() {}public void method2() {}}


注意事项:在使用单例时,一定要保证确实只需要一个实例对象。

在javaWeb中,Servlet在什么时候是单实例,什么时候是多实例?为什么要做成单实例?

1、线程安全(当然在编写Servlet时候需要遵守一些约定,譬如servlet中尽量不要有共享的实例变量,如果有就需要进行并发控制)。

2、避免过多的垃圾对象。

读书人网 >软件开发

热点推荐