Effective第三版 中英 | 第2章 创建和销毁对象 | 用私有构造器或者枚举类型强化 Singleton 属性

这篇具有很好参考价值的文章主要介绍了Effective第三版 中英 | 第2章 创建和销毁对象 | 用私有构造器或者枚举类型强化 Singleton 属性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Effective第三版

前言

大家好,这里是 Rocky 编程日记 ,喜欢后端架构及中间件源码,目前正在阅读 effective-java 书籍。同时也把自己学习该书时的笔记,代码分享出来,供大家学习交流,如若笔记中有不对的地方,那一定是当时我的理解还不够,希望你能及时提出。如果对于该笔记存在很多疑惑,可以先去翻阅《Java核心技术》也欢迎和我交流讨论,最后也感谢您的阅读,点赞,关注,收藏~

前人述备矣,我只是知识的搬运工,effective 书籍源码均在开源项目 java-diary 中的 code-effective-third 模块中

源代码仓库地址: https://gitee.com/Rocky-BCRJ/java-diary.git
Effective第三版 中英 | 第2章 创建和销毁对象 | 用私有构造器或者枚举类型强化 Singleton 属性

第二章 创建和销毁对象

用私有构造器或者枚举类型强化 Singleton 属性

   A singleton is simply a class that is instantiated exactly once [Gamma95]. Singletons typically represent either a stateless object such as a function (Item 24) or a system component that is intrinsically unique. Making a class a singleton can make it difficult to test its clients because it’s impossible to substitute a mock implementation for a singleton unless it implements an interface that serves as its type.

  Singleton 指仅仅被实例化一次的类 [Gamma95]。Singleton 通常代表无状态的对象,例如函数(第 24 项)或者本质上唯一的系统组件。使类成为 Singleton 会使它的客户端测试变得十分困难,因为除非它实现了作为其类型的接口,否则不可能将模拟实现替换为单例。

  There are two common ways to implement singletons. Both are based on keeping the constructor private and exporting a public static member to provide access to the sole instance. In one approach, the member is a final field:

  实现单例的方法有两种。 两者都基于保持构造函数私有并导出公共静态成员以提供对唯一实例的访问。 在一种方法中,该成员是 final 字段:

// Singleton with public final field
public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public void leaveTheBuilding() { ... }
}

  The private constructor is called only once, to initialize the public static final field Elvis.INSTANCE. The lack of a public or protected constructor guarantees a “monoelvistic” universe: exactly one Elvis instance will exist once the Elvis class is initialized—no more, no less. Nothing that a client does can change this, with one caveat: a privileged client can invoke the private constructor reflectively (Item 65) with the aid of the AccessibleObject.setAccessible method. If you need to defend against this attack, modify the constructor to make it throw an exception if it’s asked to create a second instance.

  私有构造器只调用一次,用来初始化静态变量Elvis.INSTANCE。由于缺少public或者protect属性的构造器,这就保证了Elvis的全局一致性:一旦Evlis类被实例化,只会存在一个Elvis实例,不多也不少。客户端所做的任何事情都无法改变这一点,但有一点需要注意:享有特权的客户端可以借助AccessibleObject.setAccessible方法反射性地调用私有构造函数(第 65 项)。如果你需要防御此攻击,请修改构造函数以使其在要求创建第二个实例时抛出异常。

  In the second approach to implementing singletons, the public member is a static factory method:

  在实现 Singleton 的第二种方法中,公有的成员是个静态工厂方法:

// Singleton with static factory
public class Elvis {
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public static Elvis getInstance() { return INSTANCE; }
    public void leaveTheBuilding() { ... }
}

  All calls to Elvis.getInstance return the same object reference, and no other Elvis instance will ever be created (with the same caveat mentioned earlier).

  对于静态方法Elvis.getInstance的所有调用,都会返回同一个对象引用,所以,永远不会创建其他的Elvis实例(上述提醒依然适用)。

  The main advantage of the public field approach is that the API makes it clear that the class is a singleton: the public static field is final, so it will always contain the same object reference. The second advantage is that it’s simpler.

  公有域方法的主要好处在于,组成类的成员的声明很清楚地声明了这个类是一个 Singleton:公有的静态域是 final 的,所以该域总是包含同一个对象的引用。第二个好处就是它更加简单。

  One advantage of the static factory approach is that it gives you the flexibility to change your mind about whether the class is a singleton without changing its API. The factory method returns the sole instance, but it could be modified to return, say, a separate instance for each thread that invokes it. A second advantage is that you can write a generic singleton factory if your application requires it (Item 30). A final advantage of using a static factory is that a method reference can be used as a supplier, for example Elvis::instance is a Supplier. Unless one of these advantages is relevant, the public field approach is preferable.

  工厂方法的优势之一在于,它提供了灵活性:在不改变其 API 的前提下,我们可以改变类是否应该为 Singleton 的想法。工厂方法返回唯一实例,但是,它可以很容易被修改,比如改成每个调用该方法的线程返回一个唯一的实例。第二个优点是,如果你的应用需要,你可以编写泛型单例工厂(第 30 项)。使用静态工厂的最后一个优点是一个方法引用可以当成一个提供者,例如Elvis::instance提供的是<Elvis>。除非跟这些优点有所关联,否则使用公有域的方法更可取。

  To make a singleton class that uses either of these approaches serializable(Chapter 12), it is not sufficient merely to add implements Serializable to its declaration. To maintain the singleton guarantee, declare all instance fields transient and provide a readResolve method (Item 89). Otherwise, each time a serialized instance is deserialized, a new instance will be created, leading, in the case of our example, to spurious Elvis sightings. To prevent this from happening, add this readResolve method to the Elvis class:

  为了利用这其中一种方法实现的 Singleton 类变成可序列化的(第 12 章),仅仅在声明中加上“implements Serializable”是不够的。为了维护并保证 Singleton,必须声明所有实例域都是瞬时(transient)的,并提供一个readResolve方法(第 89 项)。否则,每次反序列化时,都会创建一个新的实例,在我们的示例中,会导致“假冒的 Elvis”。为了防止这种情况,要在 Elvis 类中加入下面这个 readResolve 方法:

// readResolve method to preserve singleton property
private Object readResolve() {
    // Return the one true Elvis and let the garbage collector
    // take care of the Elvis impersonator.
    return INSTANCE;
}

  实现 Singleton 还有第三种方法。只需要编写一个包含单个元素的枚举类型:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

  This approach is similar to the public field approach, but it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. This approach may feel a bit unnatural, but a single-element enum type is often the best way to implement a singleton. Note that you can’t use this approach if your singleton must extend a superclass other than Enum(though you can declare an enum to implement interfaces).

  这种方法类似于使用公有域的方法,但它更简洁,免费提供序列化机制,并提供了对多个实例化的铁定保证,即使面对复杂的序列化或反射攻击。这种方法可能会有点不自然,但单元素枚举类型通常是实现单例的最佳方法。请注意,如果你的单例必须扩展Enum以外的超类,则不能使用此方法(尽管你可以声明枚举来实现接口)。文章来源地址https://www.toymoban.com/news/detail-471803.html

到了这里,关于Effective第三版 中英 | 第2章 创建和销毁对象 | 用私有构造器或者枚举类型强化 Singleton 属性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《Effective C++》第三版-1. 让自己习惯C++(Accustoming Yourself to C++)

    目录 条款01:视C++为一个语言联邦(View C++ as a federation of languages) 条款02:尽量以const、enum、inline替换#define(Prefer consts, enums, and inlines to #define) 替换原因 两种特殊常量 形似函数的宏 条款03:尽可能使用const(Use const whenever possible) const和指针 const成员函数 在const和non-co

    2024年04月28日
    浏览(35)
  • 《Effective C++》第三版-2. 构造析构赋值运算(Constructors,Destructors,and Assignment Operators)

    目录 条款05:了解C++默默编写并调用哪些函数(Know what functions C++ silently writes and calls) 自动生成的函数 举例说明 条款06:若不想使用编译器自动生成的函数,就该明确拒绝(Explicitly disallow the use of compiler-generated functions you do not want) 条款07:为多态基类声明virtual析构函数(

    2024年04月28日
    浏览(43)
  • Effective Java笔记(6)避免创建不必要的对象

            一般来说,最好能重用单个对象,而不是在每次需要 的时候就创建一个相同功能的新对象 。 重用方式既快速,又流行 。 如果对象是不可变的( immutable ) (详见第 17 条),它就始终可以被重用 。         作为一个极端的反面例子,看看下面的语句 :    

    2024年02月15日
    浏览(39)
  • Spring IOC之对象的创建方式、策略及销毁时机和生命周期且获取方式

    目录 一、对象的创建方式 1. 使用构造方法 2. 使用工厂类方法 3. 使用工厂类的静态方法 二、对象的创建策略 1. 单例策略 2. 多例策略 三、对象的销毁时机 四、生命周期方法 1. 定义生命周期方法 2. 配置生命周期方法 3. 测试 五、获取Bean对象的方式 1. 通过id/name获取 2. 通过类

    2024年02月01日
    浏览(42)
  • 人工智能(第三版)阅读笔记

      要确定人工智能的优缺点,就必须首先理解和定义智能。   R.斯腾伯格:智能是个体从经验中学习、正确推理、记忆重要信息,以及应对日常生活需求的认知能力。 不同的动物物种具有不同程度的智能,但并不是所有能够思维的物体都有智能--智能也许就是高效以及有效的思

    2024年01月23日
    浏览(51)
  • 刘鹏云计算第三版(课后习题答案)

         

    2024年02月11日
    浏览(39)
  • 人工智能(第三版)—第一章讨论题

    人工智能是机器执行与人类思维相关的认知功能的能力,例如感知、推理、学习、与环境交互、解决问题,甚至发挥创造力的未来世界的愿景。 将人工智能称之为机器可以具有人类思维相关认知能力的愿景 目前解决的方式是通过机器学习的方法来逼近人工智能这一个愿景 其

    2024年01月20日
    浏览(51)
  • 人工智能(第三版)—【第一章】练习题

    逆图灵测试的一个可能的实际应用是 在线购票系统 。在购票过程中,用户可能会遇到各种问题、疑虑或困惑,例如座位选择、票价查询、支付问题等。通过进行逆图灵测试,系统可以判断用户是在与人交互还是与另一台计算机交互,从而提供更加个性化和准确的服务。 在这

    2024年02月21日
    浏览(56)
  • 《人工智能》第三版 第一章 概述 课后习题

    第一章 讨论题 1.你如何定义人工智能? 人工智能利用计算机和机器模仿人类大脑解决问题和决策的能力 2.区分强人工智能和弱人工智能。 区分强人工智能和弱人工智能的关键在于它们的功能和应用范围:强人工智能能够执行任何人类智能任务,而弱人工智能则专注

    2024年01月25日
    浏览(48)
  • 计算机组成原理(第三版)唐朔飞-第三章系统总线-课后习题

    答: ① 总线 是连接多个部件的信息传输线,是个部件共享的传输介质。 ② 总线传输 特点 :在某一时刻,只允许有一个部件向总线发送信息,而多个部件可以同时从总线上接受相同的信息。 ③ 为减轻总线上的负载,各种I/O设备要通过 I/O接口 接在总线上,而且还要通过 三态门 挂在

    2023年04月13日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包