单例模式的目的就是要控制特定的类只产生一个对象,当然也允许在一定情况下灵活的改变对象的个数。
那么怎么来实现单例模式呢?
一个类的对象的产生是由类构造函数来完成的,如果想限制对象的产生,就要将构造函数变为私有的(至少是受保护的),使得外面的 类不能通过引用来产生对象;同时为了保证类的可用性,就必须提供一个自己的对象以及访问这个对象的静态方法。(只有一个实例对象叫单实例了)
单例模式可分为有状态的和无状态的。
有状态的单例对象一般也是可变的单例对象,多个单态对象在一起就可以作为一个状态仓库一样向外提供服务。没有状态的单例对象也就是不变单例对象,仅用做提供工具函数。
饿汉式: public class DumpDemo { private static DumpDemo instance = new DumpDemo(); private DumpDemo() {} //静态工厂方法,提供一个供外部访问得到对象的静态方法 public static DumpDemo getInstance() { return instance; } } 懒汉式: public class DumpDemo { private static DumpDemo instance = null; private DumpDemo() {} //静态工厂方法,提供一个供外部访问得到对象的静态方法 public static synchronized DumpDemo getInstance() { if (instance == null) { instance = new DumpDemo(); } return instance; } }
在第二种方式中,对静态工厂方法进行了同步处理,原因很明显——为了防止多线程环境中产生多个实例;而在第一种方式中则不存在这种情况。(防止多线程过来的破坏)
在第二种方式中将类对自己的实例化延迟到第一次被引用的时候。而在第一种方式中则是在类被加载的时候实例化,这样多次加载会照成多次实例化。但是第二种方式由于使用了同步处理,在反应速度上要比第一种慢一些。
以上两种实现方式均失去了多态性,不允许被继承。还有另外一种灵活点的实现,将构造函数设置为受保护的,这样允许被继承产生子类。
import java.util.HashMap; public class DumpDemo { private static HashMap sinRegistry = new HashMap(); private static DumpDemo s = new DumpDemo(); protected DumpDemo() {} //静态工厂方法,提供一个供外部访问得到对象的静态方法 public static DumpDemo getInstance(String name) { if(name == null) name = "Singleton"; if(sinRegistry.get(name)==null){ try{ sinRegistry.put(name , Class.forName(name).newInstance()); }catch(Exception e) { e.printStackTrace(); } } return (DumpDemo)(sinRegistry.get(name)); } public void test() { System.out.println("getclasssuccess!"); } } class SingletonChild1 extends DumpDemo{ public SingletonChild1(){} static public SingletonChild1 getInstance() { //子类中可以获取到一个实例 return (SingletonChild1)DumpDemo.getInstance("SingletonChild1"); } public void test() { System.out.println("getclasssuccess111!"); } }