第一篇 生成及初始化对象 第一章 - 单例模式
类实例化(instantiate)后会生成对象。
由同一个类经过多次实例化生成的若干对象可以封装不同的数据,产生不同的行为。看个例子。
// 西湖
public class Xihu {
private String state;
public Xihu(String state) {
this.state = state;
}
public void show() {
if ("晴".equals(this.state)) {
// 水光潋滟
}
if ("雨".equals(this.state)) {
// 山色空蒙
}
}
}
// 测试类
public class Test {
public Test() {
Xihu obj1 = new Xihu("晴");// 第一次实例化
Xihu obj2 = new Xihu("雨");// 第二次实例化
obj1.show();
obj2.show();
}
}
“西湖”类经过两次实例化生成了 obj1 和 obj2 两个对象。它们分别封装了“晴”“雨”两种状态数据,可以展现不同天气时的西湖美景。
进一步观察发现,obj1 和 obj2 各自代表了西湖的一个侧面,把它们结合起来才能描绘“水光潋滟晴方好,山色空蒙雨亦奇”的完整画卷。
这是面向对象风格(Object-oriented Style)的重要特征:由一个类生成多个对象,对象之间彼此分离又相互补充,共同完成该类的全部功能。
笔者将这个特征概括为“对象多样性”。
对象多样性是具有普遍意义的矛盾之对立统一规律在面向对象领域的体现,也是我们思考问题的重要出发点。关于它的话题,后续章节还有涉及。本章只讨论一个特殊的情形——单例模式。
单例模式是要求某个类只能生成一个对象的设计模式。
一个典型的例子是代表 Java 应用运行环境的 Runtime 类。看下源码(有改动)。
public class Runtime {
private static Runtime obj = new Runtime();// 提前准备好的对象
public static Runtime get() {// 获取对象的方法
return obj;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}// 只能在本类中访问的构造方法
}
Runtime 类的构造方法(实例化的入口)是私有的,我们不能随意生成它的对象,只能通过 get() 方法获取作者提前准备好的 obj 对象。这样一来,obj 成了全局唯一的 Runtime 类对象。
这是经典的单例模式写法,简单且实用。
下面是一些常见的单例模式使用场景:
(1)对象居于决策地位或具有全局唯一性含义。此时若多个对象并存又各自为政,容易引发“脑裂”现象,造成系统紊乱。负责生成业务单据流水号的对象属于此种情形。
(2)生成对象的开销较大。随意生成这种对象容易降低系统性能。“线程池”属于此种情形,它们通常会占用较多的系统资源。
(3)对象被用来组装成更大的对象。对象之间可能有复杂的依赖关系,使它们保持唯一可以简化组装过程。Spring Framework托管的对象即被默认为单例模式。下面是单例对象的组装过程示意图。

浙公网安备 33010602011771号