黑马程序员技术交流社区

标题: 程序设计之 单例模式 深入研究 [打印本页]

作者: 周志龙    时间: 2013-10-14 18:28
标题: 程序设计之 单例模式 深入研究
一、问题的引出

目的:设计一个加密的工具类。

写法一:【单例模式】
  1. public class CipherUtils {  
  2.     private List key;  
  3.     private static CipherUtils instance;  
  4.     private CipherUtils(String... args){  
  5.         // TODO 比较复杂的初始化KEY的过程  
  6.     }   
  7.     public static boolean initInstance(String... args){  
  8.         instance = new CipherUtils(args);  
  9.         return true;  
  10.     }  
  11.     public static CipherUtils getInstance(){  
  12.         return instance;  
  13.     }  
  14.         
  15.     // 正在用到的加密方法  
  16.     public String doCipher(String... args){  
  17.         // TODO  
  18.         Map map = new HashMap();  
  19.         map.put("key", key);  
  20.         return null;  
  21.     }  
  22. }  

  23. 》》调用方法:

  24. CipherUtils cu= CipherUtils.getInstance();

  25.                 cu.doCipher(...);
复制代码
写法二:【静态方法模式】
  1. public class CipherUtils {  
  2.     private static List key;  
  3.     // 正在用到的加密方法  
  4.     public static String doCipher(String... args){  
  5.         // TODO  
  6.         Map map = new HashMap();  
  7.         map.put("key", key);  
  8.         return null;  
  9.     }  
  10.     // 比较复杂的初始化KEY的过程  
  11.     public static void initKey(String... args){  
  12.         // TODO  
  13.     }  
  14. }  
复制代码
》》调用方法:CipherUtils.doCipher(...);



注意以上例子,只是一个模拟,真实情况 类的属性可能不止一个,可能有三个以上属性。



写法一的特点:

1、使用时调的方法都是非static的(doCipher等等)

2、类的属性都是非static的。

3、拥有单例模式的所有优点。

写法二的优点:

1、属性和方法都是static的。

2、static是全局共享的,所以也拥有单例模式的核心优点。



另外,还注意到一点,单例模式 有一个比 静态方法模式 更好的地方:

它可以被继承,方法可以被子类重载,所以扩展性更强。

例如一个子类SubCipher重载了doCipher方法,那么调用方式如下:

CipherUtils cu= SubCipher.getInstance();

                cu.doCipher(...);

注意到,调用处(第二行)是无需修改代码的。但是如果是静态方法的话,只能重命名一个方法了,而且调用出还要改代码,比如:

CipherUtils.doCipher_02(...);



二、问题的研究

  这一部分主要参考了网上3、4篇关于类似问题的讨论。

  比如:




三、总结

  1、搞清楚单例模式的缺点和优势,不要乱用。

    一般我不用单例模式,因为这样增加了代码管理成本。但是以下几个场景最好用单例模式:

1)场景一:类可能会有继承、方法可能需要重载。(Spring里面有些东西就是这样设计的)

2)场景二:类的所有属性需要保持一致性,(要么都改变,要么都不改变),且这个类的方法较多(5个以上)。单例模式实现这个功能就比较方便,直接把原来缓存的static实例对象整体替换掉,重新new一个就可以了,

但是如果用静态方法来实现,则在更新属性时,需要停止所有的static方法被调用,也就意味着,要在所有的方法中加上synchronized关键字,即:单例模式只需要同步getInstance这个方法就可以,而静态方法模式,需要同步所有的方法。

如果类的实例方法不多,在5个以内,那其实给每个方法都加上synchronized关键字那也无所谓,反正效率上讲,静态方法还稍微高一些,但是如果方法多了,则还是采用单例模式吧。

  2、就我上面,那个问题而言,最好是采用静态方法模式,因为只有一个doCipher方法,不符合场景二,而且本身是个工具类,无需类的继承,所以也不符合场景一。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2