5.3.10 思考单例模式
1、单例模式的本质
单例模式的本质:控制实例数目。
单例模式是为了控制在运行期间,某些类的实例数目只能有一个。可能有人就会思考,能不能控制实例数目为2个,3个,或者是任意多个呢?目的都是一样的,节约资源啊,有些时候单个实例不能满足实际的需要,会忙不过来,根据测算,3个实例刚刚好。也就是说,现在要控制实例数目为3个,怎么办呢?
其实思路很简单,就是利用上面通过Map来缓存实现单例的示例,进行变形,一个Map可以缓存任意多个实例。新的问题是,Map中有多个实例,但是客户端调用的时候,到底返回哪一个实例呢,也就是实例的调度问题,我们只是想来展示设计模式,对于调度算法就不去深究了,做个最简单的循环返回就好可以了。示例代码如下: - /**
- * 简单演示如何扩展单例模式,控制实例数目为3个
- */
- public class OneExtend {
- /**
- * 定义一个缺省的key值的前缀
- */
- private final static String DEFAULT_PREKEY = "Cache";
- /**
- * 缓存实例的容器
- */
- private static Map<String,OneExtend> map =
- new HashMap<String,OneExtend>();
- /**
- * 用来记录当前正在使用第几个实例,到了控制的最大数目,就返回从1开始
- */
- private static int num = 1;
- /**
- * 定义控制实例的最大数目
- */
- private final static int NUM_MAX = 3;
- private OneExtend(){}
- public static OneExtend getInstance(){
- String key = DEFAULT_PREKEY+num;
- OneExtend oneExtend = map.get(key);
- if(oneExtend==null){
- oneExtend = new OneExtend();
- map.put(key, oneExtend);
- }
- //把当前实例的序号加1
- num++;
- if(num > NUM_MAX){
- //如果实例的序号已经达到最大数目了,那就重复从1开始获取
- num = 1;
- }
- return oneExtend;
- }
-
- public static void main(String[] args) {
- OneExtend t1 = getInstance ();
- OneExtend t2 = getInstance ();
- OneExtend t3 = getInstance ();
- OneExtend t4 = getInstance ();
- OneExtend t5 = getInstance ();
- OneExtend t6 = getInstance ();
-
- System.out.println("t1=="+t1);
- System.out.println("t2=="+t2);
- System.out.println("t3=="+t3);
- System.out.println("t4=="+t4);
- System.out.println("t5=="+t5);
- System.out.println("t6=="+t6);
- }
- }
测试一下,看看结果,如下: - t1==cn.javass.dp.singleton.example9.OneExtend@6b97fd
- t2==cn.javass.dp.singleton.example9.OneExtend@1c78e57
- t3==cn.javass.dp.singleton.example9.OneExtend@5224ee
- t4==cn.javass.dp.singleton.example9.OneExtend@6b97fd
- t5==cn.javass.dp.singleton.example9.OneExtend@1c78e57
- t6==cn.javass.dp.singleton.example9.OneExtend@5224ee
第一个实例和第四个相同,第二个与第五个相同,第三个与第六个相同。也就是说一共只有三个实例,而且调度算法是从第一个依次取到第三个,然后回来继续从第一个开始取到第三个。
当然在这里我们不去考虑复杂的调度情况,也不去考虑何时应该创建新实例的问题。
2、何时选用单例模式
建议在如下情况时,选用单例模式。
当需要控制一个类的实例只能有一个,而且客户只能从一个全局访问点访问它时,可以选用单例模式,这些功能恰好是单例模式要解决的问题。
|