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)。。。。有一个解决方法是把你的单例类放到一个外在的包中,以便在其它包中的类(包括缺省的包)无法实例化一个单例类。

  • 相关阅读:
    牛客(14)链表中倒数第k个结点
    牛客(13)调整数组顺序使奇数位于偶数前面
    牛客(12)数值的整数次方
    牛客(11)二进制中1的个数
    牛客(10)矩形覆盖
    牛客(9)变态跳台阶
    牛客(8)跳台阶
    牛客(7)斐波那契数列
    Docker数据卷
    Docker镜像
  • 原文地址:https://www.cnblogs.com/muliu/p/8176154.html
Copyright © 2011-2022 走看看