几个项目下来,对于设计模式还是比较熟悉了,比如什么适配器模式,工厂模式,单例模式,什么原型模式等等。
但是,对于单例模式还是有些东西可以好好说一下的。比如,写一个简单的单例模式的例子。下面的代码应该是大多数人的选择:
public class Singleton_Test_1{ public Singleton_Test_1() { System.out.println("I was built"); } private static Singleton_Test_1 singleton_Test_1 = new Singleton_Test_1(); public static Singleton_Test_1 getInstance() { return singleton_Test_1; } }
乍一看,确实没什么错误。但是,如果你的类中有一个简单的方法,比如:
public static void doSomething() { System.out.println("We don't need singleton_Test_1"); }
那么,此时会发生什么呢?
很显然,类被创建了,但是,这个方法我们倾向于不创建单例类,而且在使用的时候可能会降低程序的反应速度。
所以我们有了这么一个东西:
public class Singleton_Test_2 { public Singleton_Test_2() { System.out.println("I was built"); } private static Singleton_Test_2 singleton_Test_2 = null; public static Singleton_Test_2 getInstance() { if (singleton_Test_2 == null) { singleton_Test_2 = new Singleton_Test_2(); } return singleton_Test_2; } }
用一个延迟加载就能解决问题,但是,仔细看看,这个程序有没有毛病呢?其实还是有的,如果在多线程环境下,第一次调用的时候,很容易产生多个实例,这就是我们不愿意看到了。
所以,我们加了一个同步化。就像这样:
public static synchronized Singleton_Test_2 getInstance() { if (singleton_Test_2 == null) { singleton_Test_2 = new Singleton_Test_2(); } return singleton_Test_2; }
很简单的解决了问题,但是效率呢?不敢恭维。
怎么办呢?现在隆重推出Holder!看代码:
public class Singleton_Test_3 { public Singleton_Test_3() { System.out.println("Singleton_Test_3 was built"); } private static class singletonHolder{ private static Singleton_Test_3 instance = new Singleton_Test_3(); } public static Singleton_Test_3 getInstance() { return singletonHolder.instance; } }
在这个方法中,我们使用了内部类进行对实例的管理,这样既防止了不必要的构造,也可以加快读取速度。下面是我的测试代码,大家可以看看。
public class Singleton { /** * @author mikecoder * @see http://d0n9x1n.dev */ public static void main(String[] args) { //Singleton_Test_1.doSomething(); //Singleton_Test_2.doSomething(); //Singleton_Test_3.doSomething(); long time1 = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { Singleton_Test_1 singleton_Test_1 = Singleton_Test_1.getInstance(); } System.out.println(System.currentTimeMillis() - time1); time1 = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { Singleton_Test_2 singleton_Test_2 = Singleton_Test_2.getInstance(); } System.out.println(System.currentTimeMillis() - time1); time1 = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { Singleton_Test_3 singleton_Test_3 = Singleton_Test_3.getInstance(); } System.out.println(System.currentTimeMillis() - time1); } }
结果是:
dosomething:
效率:
所以,这一次就讲到这里。