`
1025250620
  • 浏览: 225929 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

枚举类型实现的单例模式(转)

阅读更多
我们常用的构造单例模式(Singleton)的方法,一般有2种

1 提供一个静态的公共属性
2 提供一个静态的公共方法

这2个方法,都是采用了私有的构造器来防止外部直接构造实例。 但我们可以用反射的方法,获得多个实例。后面我会给出测试的代码。

从1.5开始,枚举也可以用来获得单例,而且更加可靠。同时又自动提供了一些额外的功能。

先看看测试代码:

import java.lang.reflect.Constructor;  
/** 
* 测试Singleton的可靠性。 
*  
* @author 老紫竹(laozizhu.com) 
*/ 
public class TestSingleton {  
  public static void main(String[] args) {  
    testSingleton1();  
    testSingleton2();  
    testSingleton3();  
  }  
  public static void testSingleton1() {  
    try {  
      // 测试Singletom1  
      // 拿到第一个实例  
      TestSingleton1 s1 = TestSingleton1.getInstance();  
      // 测试拿到第二个实例  
      Class c1 = Class.forName("TestSingleton1");  
      Constructor[] cons = c1.getDeclaredConstructors();  
      Constructor cc1 = cons[0];  
      cc1.setAccessible(true);  
      TestSingleton1 s2 = (TestSingleton1) cc1.newInstance(null);  
      System.out.println(s1 + "/" + s2);  
      System.out.println(s1 == s2);  
    } catch (Exception ex) {  
      ex.printStackTrace();  
    }  
  }  
  public static void testSingleton2() {  
    try {  
      // 测试Singletom1  
      // 拿到第一个实例  
      TestSingleton2 s1 = TestSingleton2.getInstance();  
      // 测试拿到第二个实例  
      Class c1 = Class.forName("TestSingleton2");  
      Constructor[] cons = c1.getDeclaredConstructors();  
      Constructor cc1 = cons[0];  
      cc1.setAccessible(true);  
      TestSingleton2 s2 = (TestSingleton2) cc1.newInstance(null);  
      System.out.println(s1 + "/" + s2);  
      System.out.println(s1 == s2);  
    } catch (Exception ex) {  
      ex.printStackTrace();  
    }  
  }  
  public static void testSingleton3() {  
    try {  
      // 测试Singletom1  
      // 拿到第一个实例  
      TestSingleton3 s1 = TestSingleton3.getInstance();  
      // 测试拿到第二个实例  
      Class c1 = Class.forName("TestSingleton3");  
      Constructor[] cons = c1.getDeclaredConstructors();  
      Constructor cc1 = cons[0];  
      cc1.setAccessible(true);  
      TestSingleton3 s2 = (TestSingleton3) cc1.newInstance(null);  
      System.out.println(s1 + "/" + s2);  
      System.out.println(s1 == s2);  
    } catch (Exception ex) {  
      ex.printStackTrace();  
    }  
  }  
}  
/** 
* 一个普通的Singletone实现。 
*  
* @author 老紫竹(laozizhu.com) 
*/ 
class TestSingleton1 {  
  private static final TestSingleton1 INSTANCE = new TestSingleton1();  
  public static TestSingleton1 getInstance() {  
    return INSTANCE;  
  }  
  private TestSingleton1() {  
  }  
}  
/** 
* 一个用异常强化了的Singletone实现。 
*  
* @author 老紫竹(laozizhu.com) 
*/ 
class TestSingleton2 {  
  private static final TestSingleton2 INSTANCE = new TestSingleton2();  
  public static TestSingleton2 getInstance() {  
    return INSTANCE;  
  }  
  private static boolean initSign;  
  private TestSingleton2() {  
    if (initSign) {  
      throw new RuntimeException("实例只能建造一次");  
    }  
    initSign = true;  
  }  
}  
/** 
* 枚举实现的Singleton 
*  
* @author 老紫竹(laozizhu.com) 
*/ 
enum TestSingleton3 {  
  INSTANCE;  
  public static TestSingleton3 getInstance() {  
    return INSTANCE;  
  }  
}




测试结果
TestSingleton1@c17164/TestSingleton1@1fb8ee3
false
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at TestSingleton.testSingleton2(TestSingleton.java:43)
at TestSingleton.main(TestSingleton.java:11)
Caused by: java.lang.RuntimeException: 实例只能建造一次
at TestSingleton2.<init>(TestSingleton.java:103)
... 6 more
java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Constructor.java:511)
at TestSingleton.testSingleton3(TestSingleton.java:61)
at TestSingleton.main(TestSingleton.java:12)


小结:可见,只有第三种枚举的方法才是最安全的。

关于里面提到的,在序列化是可能出现的问题,我看以后在讨论吧。不过因为枚举实现的单例没有这个问题,所以我看以后就用枚举好了,何必自己跟自己过不去呢?
分享到:
评论

相关推荐

    一个单例模式的晋级过程(饿汉-懒汉-DCL-IoDH-枚举)

    一个单例模式的晋级过程...枚举实现单例使用推荐 什么是单例? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一

    单例模式,属于创建类型的一种常用的软件设计模式 通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中

    通常单例模式在Java语言中,有两种构建方式: 懒汉式—线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize之类的锁,以提高性能。...java中枚举类本身也是一种单例模式

    Java+单例+多例+工厂+枚举+动态代理===》演示

    单例模式,是一种常用的软件设计模式。通过单例模式可以保证系统中,**应用该模式的这个类只有一个实例**。即一个类只有一个对象实例。 #### 单例设计模式实现步骤 1. 将构造方法私有化,使其不能在类的外部通过new...

    JAVA面向对象详细资料

    32 单例模式 47 32.1 饿汉模式 47 32.2 懒汉模式 47 33 接口(interface) 48 33.1 如何创建一个接口。 48 33.2 如何使用接口 48 33.3 如何使用类实现一个接口 49 33.4 接口的细节 49 34 接口的应用(面向对象分析)...

    积分管理系统java源码-knowledge:这是我的知识,包括我所有已知的

    单例模式 & 多例模式 代理模式 策略模式 原型模式 工厂模式 委托 其他 Spring5 IOC容器设计原理及高级特性 AOP设计原理 FactoryBean和BeanFactory Spring事务处理机制 Spring JDBC Spring MVC九大组件 手动实现...

    Java基础知识点总结.docx

    单例设计模式:★★★★★ 156 工厂模式★★★★★ 159 抽象工厂模式★★★★★ 163 建造者模式 170 原型模式 177 适配器模式 182 桥接模式 188 过滤器模式 192 组合模式 193 装饰器模式★★★★★ 196 外观模式 201...

    day020-继承加强和设计模式代码和笔记.rar

    通过单例模式获取到对象后。就是只有一个对象的类 方法全部都是非static修饰的,调用方式:对象名.方法名(...); 4. 工具类命名: XxxUtil、XxxUtils、XxxTool、XxxTools 3. jar 包 (掌握)...

    基于javatcpsocket通信的拆包和装包源码-chaugod:乔戈德

    枚举: name 单例: writeReplace(), readResolve() 安全性: 网络传输 通用性: 跨平台、跨语言 可扩展性: 是否支持自动加入新的字段 性能: 空间开销(序列化大小)、时间开销(序列化/反序列化时间) 序列化协议: stream、...

    酒店管理客房系统Java源码-GOF23:Java实现23种设计模式学习笔记

    工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品,不用修改源代码)将工厂类调整为工厂接口,需要什么类型的工厂就使用该类实现该工厂,创建相应的产品。 :用来生产不同产品族的全部产品(对于...

    超级有影响力霸气的Java面试题大全文档

    引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。 21、heap和stack有什么区别。  栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的...

    快学 scala 中文版 带完整目录

    14.4 类型模式 224 14.5 匹配数组、列表和元组 225 14.6 提取器 227 14.7 变量声明中的模式 227 14.8 for表达式中的模式 229 14.9 样例类 229 14.10 copy方法和带名参数 230 14.11 case语句中的中置表示法 ...

    【05-面向对象(下)】

    把基本数据类型变量包装类实例是通过对应包装类的构造器来实现的,不仅如此,8个包装类中除了 Character之外,还可以通过传入一个字符串参数来构建包装类对象。 •如果希望获得包装类对象中包装的基本类型...

    JAVA 范例大全 光盘 资源

    实例31 单例模式(Singleton) 75 实例33 开车(简单工厂模式) 77 实例33 旅游(工厂方法模式) 79 实例34 花园布局(抽象工厂模式) 80 实例35 几何图形(适配器模式) 82 第6章 字符串 85 实例36 获取字符...

    Python Cookbook

    6.15 实现单例模式 257 6.16 用Borg惯用法来避免“单例”模式 259 6.17 Null对象设计模式的实现 263 6.18 用_ _init_ _参数自动初始化实例变量 266 6.19 调用超类的_ _init_ _方法 267 6.20 精确和安全地使用...

    java 面试题 总结

    引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。 18、heap和stack有什么区别。 栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例088 单例模式的应用 109 实例089 祖先的止痒药方 110 实例090 统计图书的销售量 111 实例091 汉诺塔问题求解 112 实例092 不能重写的方法 113 5.3 包装类的使用 114 实例093 将字符串转换成整数 114 实例094 ...

    Java JDK实例宝典

    8 Singleton单例模式 2. 9 Factory工厂模式 2. 10 Adapter适配器模式 第3章 数字 3. 1 数字与数字封装类 3. 2 格式化数字 3. 3 数字的舍入 3. 4 转换数字的进制 3. 5 生成随机数 ...

Global site tag (gtag.js) - Google Analytics