-
Notifications
You must be signed in to change notification settings - Fork 124
校对第三章 #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Fudeveloper
wants to merge
2
commits into
sjsdfg:master
Choose a base branch
from
Fudeveloper:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
校对第三章 #57
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| # 3. 使用私有构造方法或枚类实现 Singleton 属性 | ||
|
|
||
|
|
||
| 单例是一个仅实例化一次的类[Gamma95]。单例对象通常表示无状态对象,如函数 (详见第 24 条) 或一个本质上唯一的系统组件。让一个类成为单例会使测试它的客户变得困难,因为除非实现一个作为它类型的接口,否则不可能用一个模拟实现替代单例。 | ||
| 单例是一个仅实例化一次的类[Gamma95]。单例对象通常表示无状态对象,如函数(条目 24) 、或一个本质上唯一的系统组件。**让一个类成为单例会使测试它的客户端变得困难**,因为需要创建一个实现该接口的类,否则无法用模拟实现替代单例。 | ||
|
|
||
| 有两种常见的方法来实现单例。两者都基于保持构造方法私有和导出公共静态成员以提供对唯一实例的访问。在第一种方法中,成员是 `final` 修饰的属性: | ||
|
|
||
|
|
@@ -14,7 +14,7 @@ public class Elvis { | |
| } | ||
| ``` | ||
|
|
||
| 私有构造方法只调用一次,来初始化公共静态 final `Elvis.INSTANCE` 属性。缺少一个公共的或受保护的构造方法,保证了全局的唯一性:一旦 Elvis 类被初始化,一个 Elvis 的实例就会存在——不多也不少。客户端所做的任何事情都不能改变这一点,但需要注意的是:特权客户端可以使用 `AccessibleObject.setAccessible` 方法,以反射方式调用私有构造方法(详见第 65 条)。如果需要防御此攻击,请修改构造函数,使其在请求创建第二个实例时抛出异常。 | ||
| 私有构造方法只调用一次,来初始化`public static final Elvis.INSTANCE` 属性。不声明一个公共的或受保护的构造方法,保证了全局的唯一性:一旦 Elvis 类被初始化,一个 Elvis 的实例就会存在——不多也不少。客户端所做的任何事情都不能改变这一点,但需要注意的是:特权客户端可以使用 `AccessibleObject.setAccessible` 方法,以反射方式调用私有构造方法(详见第 65 条)。如果需要防御此攻击,请修改构造函数,使其在请求创建第二个实例时抛出异常。 | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 英文字符前后加空格 |
||
|
|
||
| 在第二个实现单例的方法中,公共成员是一个静态的工厂方法: | ||
|
|
||
|
|
@@ -31,9 +31,9 @@ public class Elvis { | |
|
|
||
| 所有对 `Elvis.getInstance` 的调用都返回相同的对象引用,并且不会创建其他的 Elvis 实例(与前面提到的警告相同)。 | ||
|
|
||
| 公共属性方法的主要优点是 API 明确表示该类是一个单例:公共静态属性是 final 的,所以它总是包含相同的对象引用。 第二个好处是它更简单。 | ||
| 公共属性方法的主要优点是: API 明确表示该类是一个单例:公共静态属性是 final 的,所以它总是包含相同的对象引用。 第二个好处是它更简单。 | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个搞两个冒号不觉得奇怪么。 这前面本身就是一句话,如果想分隔你也要用逗号 |
||
|
|
||
| 静态工厂方法的优势之一在于,它提供了灵活性:在不改变其 API 的前提下,我们可以改变该类是否应该为单例的想法。工厂方法返回该类的唯一实例,但是,它很容易被修改,比如,改为每个调用该方法的线程返回一个唯一的实例。 第二个好处是,如果你的应用程序需要它,可以编写一个泛型单例工厂(generic singleton factory )(详见第30 条)。 使用静态工厂的最后一个优点是,可以通过方法引用(method reference)作为提供者,例如 `Elvis::instance` 等同于 `Supplier<Elvis>`。 除非满足以上任意一种优势,否则还是优先考虑公有域(public-field)的方法。 | ||
| 静态工厂方法的优势之一在于,它提供了灵活性:在不改变其 API 的前提下,我们可以改变该类是否应该为单例的想法。工厂方法返回该类的唯一实例,但是,它可能被修改,比如,改为每个调用该方法的线程返回一个唯一的实例。 第二个好处是,如果你的应用程序需要,可以编写一个泛型单例工厂(generic singleton factory )(详见第30 条)。 使用静态工厂的最后一个优点是,可以通过方法引用(method reference)作为提供者,例如 `Elvis::instance` 等同于 `Supplier<Elvis>`。 除非满足以上任意一种优势,否则还是优先考虑公有域(public-field)的方法。 | ||
|
|
||
| 为了将上述方法中实现的单例类变成是可序列化的 (第 12 章),仅仅将 `implements Serializable` 添加到声明中是不够的。为了保证单例模式不被破坏,必须声明所有的实例字段为 `transient`,并提供一个 `readResolve` 方法(详见第 89 条)。否则,每当序列化的实例被反序列化时,就会创建一个新的实例,在我们的例子中,导致出现新的 Elvis 实例。为了防止这种情况发生,将如下的 `readResolve` 方法添加到 Elvis 类: | ||
|
|
||
|
|
@@ -56,4 +56,4 @@ public enum Elvis { | |
| } | ||
| ``` | ||
|
|
||
| 这种方式类似于公共属性方法,但更简洁,无偿地提供了序列化机制,并提供了防止多个实例化的坚固保证,即使是在复杂的序列化或反射攻击的情况下。这种方法可能感觉有点不自然,但是 **单一元素枚举类通常是实现单例的最佳方式**。注意,如果单例必须继承 `Enum` 以外的父类(尽管可以声明一个 `Enum` 来实现接口),那么就不能使用这种方法。 | ||
| 这种方式类似于公共属性方法,但更简洁,它无偿地提供了序列化机制,并提供了防止多个实例化的坚固保证,即使是在复杂的序列化或反射攻击的情况下。这种方法可能感觉有点不自然,但是 **单一元素枚举类通常是实现单例的最佳方式**。注意,如果单例必须继承 `Enum` 以外的父类 (尽管可以声明一个 `Enum` 来实现接口),那么就不能使用这种方法。 | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
用(详见第 xx 条)吧,如果没有这种形式的,都是我改漏了
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless 你这里翻译丢掉了吧