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

枚举增强单例模式的可靠性

阅读更多
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/java2000_net/archive/2009/03/12/3983958.aspx#

我们常用的构造单例模式(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)

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

相关推荐

    枚举小结

    枚举(Enum)在编程语言中是一种特殊的数据类型,...正确地使用枚举可以提升软件的维护性和可靠性,降低出错概率。在阅读`kino.iteye.com/blog/204949`这篇博文时,你可以期待学习到更多关于枚举的实用技巧和最佳实践。

    Java枚举数据类型.doc

    枚举类型是Java中一个强大的工具,它提高了代码的类型安全性和可读性,同时也提供了许多其他高级特性,如枚举方法和接口实现,使得在处理固定集合的值时更加方便和可靠。在编写Java程序时,特别是在定义固定选项或...

    高质量C++-C编程指南

    第7章《设计模式和最佳实践》可能会介绍一些常见的设计模式,如工厂模式、单例模式、观察者模式等,这些模式是解决常见问题的成熟方案,可以提高代码的可扩展性和可维护性。 总的来说,《高质量C++/C编程指南》是一...

    C++编程思想全集

    10. **设计模式**:学习常见的设计模式,如工厂模式、单例模式、观察者模式等,可以提升软件设计能力。 通过这两卷书的学习,读者不仅可以掌握C++语言的基本技能,还能深入了解其背后的编程理念,为成为熟练的C++...

    阿里巴巴java开发手册嵩山版.zip

    - **单例模式**:推荐使用枚举单例,避免并发问题和序列化问题。 - **工厂模式**:用于创建对象,减少代码耦合,提高可扩展性。 - **观察者模式**:实现事件驱动编程,让多个对象可以监听并响应特定事件。 5. **...

    guava-19.0

    - Guava提供了枚举Set和EnumMap,以及Guava的单例模式实现,这些在19.0版本中可能更加强大和可靠。 9. **预计算(.memoize)和断言(Preconditions)**: - Guava提供了预计算功能,用于优化计算密集型操作,而...

    拼多多java开发面试题

    - 复制机制保证了数据的冗余,增强了系统的可靠性。 2. **Redis集群** - Redis集群提供了一个高性能、可扩展的数据存储解决方案。 - 它通过数据分区实现水平扩展,每个节点负责一部分数据。 - 支持故障转移和...

    ThinkinginJAVA第四版中文版

    11. **设计模式**:《Thinking in JAVA》强调了面向对象设计原则和经典设计模式,如工厂模式、单例模式、观察者模式等,这些模式在解决常见软件问题时非常有效。 12. **测试与调试**:书中还会介绍单元测试和调试...

    现代编程语言- Kotlin 之美 - 当下最火的编程语言欣赏.pdf

    通过这种方式,`internal`关键字有效地帮助开发人员控制了代码的可见性,增强了封装性,从而使得代码更加安全可靠。 ### 结语 Kotlin通过对《Effective Java》等经典指南的深入研究与实践,不仅吸收了其精髓,还在...

    commons-lang3-3.11-bin.tar.gz

    此版本主要针对服务器端的非空校验提供了支持,确保数据处理的安全性和可靠性。 Apache Commons Lang 3.11版主要包含以下几个关键知识点: 1. **非空校验(Null Check)**:在服务器端编程中,确保对象不为null是...

    C++高级参考手册.zip(.pdf格式)

    10. **设计模式**:书中可能涉及常见的设计模式,如工厂模式、单例模式、观察者模式等,这些都是软件工程中解决特定问题的有效模式。 通过阅读《C++高级参考手册》,开发者不仅能深入理解C++的语法和特性,还能掌握...

    改善C#的157个建议编写高质量代码.zip

    11. **设计模式**:了解并应用常见的设计模式,如工厂模式、单例模式、观察者模式等,以解决常见问题。 12. **代码重构**:定期进行代码重构,以保持代码的整洁和可维护性,但要注意不要过度重构。 13. **枚举与...

    c++资源大全,希望对大家有所帮助谢谢

    12. **设计模式**:C++资源可能涵盖了一些常见的设计模式,如工厂模式、单例模式、观察者模式等,这些都是软件工程中解决常见问题的标准化解决方案。 通过深入学习和理解这些知识点,并结合提供的“C++指南”,学习...

    thinking in java 4th answer

    10. **设计模式**:《Thinking in Java》也涵盖了多种经典的设计模式,如工厂模式、单例模式、装饰器模式等,这些都是软件开发中常用的最佳实践。 通过这些知识点的学习和实践,读者可以全面提高Java编程技能,为...

    北大青鸟 Y2java电子书

    - **自动垃圾回收**:减少了程序员对内存管理的需求,提高了程序的安全性和可靠性。 #### 2. Java核心概念 - **类与对象**:类是对象的模板,对象是类的具体实例。 - **继承**:子类可以继承父类的属性和方法。 - *...

    Effective C++ & More Effective C++

    10. **设计模式**:虽然不是主要内容,但书中也提到了一些常见的设计模式,如工厂模式、单例模式,如何在C++中实现和利用它们。 11. **内存管理**:讲解了内存分配和释放的策略,如使用`new`和`delete`,以及如何...

    kotlin中文版参考手册

    同时,Kotlin在类型系统和空值安全方面做了大量工作,避免了许多常见的编程错误,提高了代码的稳定性和可靠性。 《Kotlin中文版参考手册》包含以下主要知识点: 1. **基础语法**:包括变量声明、数据类型(如基本...

    零度 C#编码规范+改善C#程序的157个建议

    12. **遵循设计模式**:理解和应用常见的设计模式,如工厂模式、单例模式、观察者模式等,以提高代码的灵活性和可扩展性。 13. **异常安全的构造函数**:确保类的构造函数在出现异常时能够正确清理已分配的资源,...

    提高C#编程水平的50个要点

    12. **设计模式**:理解并应用工厂模式、单例模式、观察者模式等常见设计模式,提升代码结构。 13. **.NET框架**:熟悉BCL(Base Class Library)中的各种类库,如System.IO、System.Net等。 14. **异构系统集成**...

Global site tag (gtag.js) - Google Analytics