暂无图片
暂无图片
暂无图片
暂无图片
暂无图片
第3项:用私有构造器或者枚举类型强化Singleton属性.pdf
144
2页
0次
2022-12-10
免费下载
用私有构造器或者枚举类型强化 Singleton 属性
  Singleton 指仅仅被实例化一次的类 [Gamma95]Singleton 通常代表无状态的对象,例如函数
(第 24 项)或者本质上唯一的系统组件。使类成为 Singleton 会使它的客户端测试变得十分困难,因
为除非它实现了作为其类型的接口,否则不可能将模拟实现替换为单例。
  实现单例的方法有两种。 两者都基于保持构造函数私有并导出公共静态成员以提供对唯一实例的访
问。 在一种方法中,该成员是 final 字段:
  私有构造器只调用一次,用来初始化静态变量 Elvis.INSTANCE 。由于缺少 public 或者 protect
属性的构造器,这就保证了 Elvis 的全局一致性:一旦 Evlis 类被实例化,只会存在一个 Elvis
例,不多也不少。客户端所做的任何事情都无法改变这一点,但有一点需要注意:享有特权的客户端可
以借助 AccessibleObject.setAccessible 方法反射性地调用私有构造函数(第 65 项)。如果你需
要防御此攻击,请修改构造函数以使其在要求创建第二个实例时抛出异常。
  在实现 Singleton 的第二种方法中,公有的成员是个静态工厂方法:
  对于静态方法 Elvis.getInstance 的所有调用,都会返回同一个对象引用,所以,永远不会创建
其他的 Elvis 实例(上述提醒依然适用)。
  公有域方法的主要好处在于,组成类的成员的声明很清楚地声明了这个类是一个 Singleton:公有
的静态域是 final 的,所以该域总是包含同一个对象的引用。第二个好处就是它更加简单。
  工厂方法的优势之一在于,它提供了灵活性:在不改变其 API 的前提下,我们可以改变类是否应该
Singleton 的想法。工厂方法返回唯一实例,但是,它可以很容易被修改,比如改成每个调用该方法
的线程返回一个唯一的实例。第二个优点是,如果你的应用需要,你可以编写泛型单例工厂(第 30
项)。使用静态工厂的最后一个优点是一个方法引用可以当成一个提供者,例如 Elvis::instance
供的是<Elvis>。除非跟这些优点有所关联,否则使用公有域的方法更可取。(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<Elvis> .Unless one of these advantages is relevant, the public field
approach is preferable.)
  为了利用这其中一种方法实现的 Singleton 类变成可序列化的( 12 ),仅仅在声明中加上
“implements Serializable”是不够的。为了维护并保证 Singleton,必须声明所有实例域都是瞬时
(transient)的,并提供一个 readResolve 方法( 89 )。否则,每次反序列化时,都会创建一个新的
实例,在我们的示例中,会导致假冒的 Elvis”。为了防止这种情况,要在 Elvis 类中加入下面这个
readResolve 方法:
// Singleton with public final field
public class Elvis {
 public static final Elvis INSTANCE = new Elvis();
 private Elvis() { ... }
 public void leaveTheBuilding() { ... }
}
// 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() { ... }
}
  实现 Singleton 还有第三种方法。只需要编写一个包含单个元素的枚举类型:
  这种方法类似于使用公有域的方法,但它更简洁,免费提供序列化机制,并提供了对多个实例化的
铁定保证,即使面对复杂的序列化或反射攻击。这种方法可能会有点不自然,但单元素枚举类型通常是
实现单例的最佳方法。请注意,如果你的单例必须扩展 Enum 以外的超类,则不能使用此方法(尽管你
可以声明枚举来实现接口)。
2 项:当面临多个参数的构造器时考虑使用构建器
4 项:通过私有构造器强化不可实例化的能力
// 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;
}
// Enum singleton - the preferred approach
public enum Elvis {
 INSTANCE;
 public void leaveTheBuilding() { ... }
}
of 2
免费下载
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文档的来源(墨天轮),文档链接,文档作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

关注
最新上传
暂无内容,敬请期待...
下载排行榜
Top250 周榜 月榜