zoukankan      html  css  js  c++  java
  • 设计模式--单例模式(二)登记式

    登记式实际对一组单例模式进行的维护,主要是在数量上的扩展,通过map我们把单例存进去,这样在调用时,先判断该单例是否已经创建,是的话直接返回,不是的话创建一个登记到map中,再返回。对于数量又分为固定数量和不固定数量的。下面采用的是不固定数量的方式,在getInstance方法中加上参数(string name)。然后通过子类继承,重写这个方法将name传进去。让我们看看代码吧。

    首先是父类:

    [java] view plain copy
     
    1. //采用Map配置多个单例  
    2. public class MySingleton3 {  
    3.       
    4.     // 设立静态变量,直接创建实例  
    5.     private static Map<String, MySingleton3> map = new HashMap<String, MySingleton3>();  
    6.           
    7.     // -----受保护的-----构造函数,不能是私有的,但是这样子类可以直接访问构造方法了  
    8.     //解决方式是把你的单例类放到一个外在的包中,以便在其它包中的类(包括缺省的包)无法实例化一个单例类。  
    9.     protected MySingleton3() {  
    10.         System.out.println("-->私有化构造函数被调用,创建实例中");  
    11.           
    12.     }  
    13.   
    14.     // 开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回  
    15.     public static MySingleton3 getInstance(String name) {  
    16.         if (name == null) {  
    17.             name = MySingleton3.class.getName();  
    18.             System.out.println("-->name不存在,name赋值等于"+MySingleton3.class.getName());  
    19.         }  
    20.         if (map.get(name) == null) {  
    21.             try {  
    22.                 System.out.println("-->name对应的值不存在,开始创建");  
    23.                 map.put(name, (MySingleton3)Class.forName(name).newInstance());  
    24.             } catch (InstantiationException e) {  
    25.                 e.printStackTrace();  
    26.             } catch (IllegalAccessException e) {  
    27.                 e.printStackTrace();  
    28.             } catch (ClassNotFoundException e) {  
    29.                 e.printStackTrace();  
    30.             }  
    31.         }else {  
    32.             System.out.println("-->name对应的值存在");  
    33.         }  
    34.         System.out.println("-->返回name对应的值");  
    35.         return map.get(name);  
    36.     }  
    37.       
    38.     public Map<String, MySingleton3> getMap(){  
    39.         return map;  
    40.     }  
    41. }  


    然后写了俩个子类:

    [java] view plain copy
     
    1. public class MySingleton3Childa extends MySingleton3 {  
    2.       
    3.     public static MySingleton3Childa getInstance() {  
    4.         return (MySingleton3Childa) MySingleton3Childa  
    5.                 .getInstance("com.xq.mysingleton.MySingleton3Childa");  
    6.     }  
    7.   
    8.     //随便写一个测试的方法  
    9.     public String about() {  
    10.         return "---->我是MySingleton3的第一个子类MySingleton3Childa";  
    11.     }  
    12. }  
    [java] view plain copy
     
    1. public class MySingleton3Childb extends MySingleton3 {  
    2.       
    3.     static public MySingleton3Childb getInstance() {  
    4.         return (MySingleton3Childb) MySingleton3Childb  
    5.                 .getInstance("com.xq.mysingleton.MySingleton3Childb");  
    6.     }  
    7.   
    8.     //随便写一个测试的方法  
    9.     public String about() {  
    10.         return "---->我是MySingleton3的第二个子类MySingleton3Childb";  
    11.     }  
    12. }  



    然后是客户端代码,这回测试用例比较多哈:

    [java] view plain copy
     
    1.        /** 
    2.  * 登记式单例模式 
    3.  * MySingleton2 
    4.  */  
    5. public static void myprint3(){  
    6.     System.out.println("-----------------登记式单例模式----------------");  
    7.     System.out.println("第一次取得实例(登记式)");  
    8.     MySingleton3 s1 = MySingleton3.getInstance(null);  
    9.     System.out.println(s1);  
    10.     System.out.println("第二次取得实例(登记式)");  
    11.     MySingleton3Childa s3 = MySingleton3Childa.getInstance();  
    12.     System.out.println(s3);  
    13.     System.out.println(s3.about());  
    14.     System.out.println("第三次取得实例(登记式)");  
    15.     MySingleton3Childb s4 = MySingleton3Childb.getInstance();  
    16.     System.out.println(s4);  
    17.     System.out.println(s4.about());  
    18.     System.out.println("第四次取得实例(非正常直接new子类的构造方法)");  
    19.     MySingleton3Childb s5 = new MySingleton3Childb();  
    20.     System.out.println(s5);  
    21.     System.out.println(s5.about());  
    22.     System.out.println("输出父类中Map保存的所有单例,可以看出,直接new出来的实例并没有存在Map中");  
    23.     System.out.println(s1.getMap());  
    24.     System.out.println();  
    25. }  
    26.   
    27.   
    28. /** 
    29.  * @param args 
    30.  */  
    31. public static void main(String[] args) {  
    32.     // TODO Auto-generated method stub  
    33.     //懒汉式  
    34.     //myprint();  
    35.     //饿汉式  
    36.     //myprint2();  
    37.     //懒汉式改进  
    38.     //myprint2a();  
    39.     //登记式  
    40.     myprint3();  
    41.   
    42. }  



    先让我们看下输出结果:

    -----------------登记式单例模式----------------
    第一次取得实例(登记式)
    -->name不存在,name赋值等于com.xq.mysingleton.MySingleton3
    -->name对应的值不存在,开始创建
    -->私有化构造函数被调用,创建实例中
    -->返回name对应的值
    com.xq.mysingleton.MySingleton3@6e1408
    第二次取得实例(登记式)
    -->name对应的值不存在,开始创建
    -->私有化构造函数被调用,创建实例中
    -->返回name对应的值
    com.xq.mysingleton.MySingleton3Childa@f62373
    ---->我是MySingleton3的第一个子类MySingleton3Childa
    第三次取得实例(登记式)
    -->name对应的值不存在,开始创建
    -->私有化构造函数被调用,创建实例中
    -->返回name对应的值
    com.xq.mysingleton.MySingleton3Childb@1f33675
    ---->我是MySingleton3的第二个子类MySingleton3Childb
    第四次取得实例(非正常直接new子类的构造方法)
    -->私有化构造函数被调用,创建实例中
    com.xq.mysingleton.MySingleton3Childb@7c6768
    ---->我是MySingleton3的第二个子类MySingleton3Childb
    输出父类中Map保存的所有单例,可以看出,直接new出来的实例并没有存在Map中
    {com.xq.mysingleton.MySingleton3Childa=com.xq.mysingleton.MySingleton3Childa@f62373, com.xq.mysingleton.MySingleton3Childb=com.xq.mysingleton.MySingleton3Childb@1f33675, com.xq.mysingleton.MySingleton3=com.xq.mysingleton.MySingleton3@6e1408}


    有点乱哈,让我们分析下。

    先后总共我们创建创建了4个单例。

    第一种情况是我们直接调用父类的方法,传入空值,结果调用父类的方法创建一个实例,并且登记在map中,后期打印可知为

    com.xq.mysingleton.MySingleton3=com.xq.mysingleton.MySingleton3@6e1408

    第二种情况是我们调用子类a的方法,由a创建一个实例并且登录在父类的map中。后期打印可知为

    com.xq.mysingleton.MySingleton3Childa=com.xq.mysingleton.MySingleton3Childa@f62373

    第三种情况是我们调用子类b的方法,由a创建一个实例并且登录在父类的map中。后期打印可知为

    com.xq.mysingleton.MySingleton3Childb=com.xq.mysingleton.MySingleton3Childb@1f33675

    第四种情况是我们直接调用子类b的构造函数,如上虽然我们创建了一个实例com.xq.mysingleton.MySingleton3Childb@7c6768,但是并没有存在map中。

    其实这也是这个解决方案的缺点,因为我们将父类构造方法对外公开了(protected)。。。。有一个解决方法是把你的单例类放到一个外在的包中,以便在其它包中的类(包括缺省的包)无法实例化一个单例类。

  • 相关阅读:
    86. Partition List
    328. Odd Even Linked List
    19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)
    24. Swap Nodes in Pairs
    2. Add Two Numbers(2个链表相加)
    92. Reverse Linked List II(链表部分反转)
    109. Convert Sorted List to Binary Search Tree
    138. Copy List with Random Pointer
    为Unity的新版ugui的Prefab生成预览图
    ArcEngine生成矩形缓冲区
  • 原文地址:https://www.cnblogs.com/muliu/p/8176154.html
Copyright © 2011-2022 走看看