在阎宏博士的《JAVA与模式》一书中开头是这样描述不变(Immutable)模式的:一个对象的状态在对象被创建之后就不再变化,这就是所谓的不变模式。
不变模式的结构
不变模式可增强对象的健壮性(robustness)。不变模式允许共享某一个对象,降低了并发访问该对象的同步开销。如果需要修改一个不变对象的状态,则需要建立一个新的同类型对象,并在创建时把这个新的状态存储在新对象里。不变模式只涉及到一个类。一个类的内部状态创建后,在整个生命周期都不会发生变化,这样的类称为不变类。使用不变类的做法叫不变模式。不变模式有两种形式:弱不变模式和强不变模式。
弱不变模式
一个类的实例状态是不可变的,但是这个类的子类的实例状态可能会变化。这样的类符合弱不变模式。要实现弱不变模式,一个类必须满足下面3个条件:
1 通过构造函数初始化对象状态后,对象状态不再改变。
2 所有属性都是私有的。
3 防止外界修改相关的其他可变对象,尽量在不变对象内部初始化这些对象。
弱不变模式的缺点:
1 一个弱不变对象的子对象可能是可变的。
2 可变的子对象可能会修改父对象的状态,从而可能会从外界修改父对象的状态。
强不变模式
一个类的实例状态不会改变,它的子类的实例状态也不会改变。这样的类符合强不变模式。要实现强不变模式,一个类必须首先满足弱不变模式要求的所有条件,并且要满足下面条件之一:
1 类所有的方法都是final,这个类的子类无法重写父类方法。
2 类本身是final,这个类就不会有子类。
“不变”和“只读”的区别
当一个变量是“只读”时,变量的值不能直接改变,可以在其他变量改变时改变。例如,一个人的出生年月日是“不变”属性,而一个人的年龄是“只读”属性,不是“不变”属性。
不变模式在Java中的应用
最著名的是java.lang.String类。它是一个强不变类型,举例:
1 String a = "test"; 2 String b = "test"; 3 String c = "test";
Java虚拟机只会创建一个字符串实例,而这3个String对象共享这一个值。
不变模式的优点
不变对象可以节省同步开销,比可变对象更加容易维护。
不变模式的缺点
如果需要修改一个不变对象的状态,就只能创建一个新的同类对象,容易出现资源浪费。
所以,只有对象状态不可能改变,才能把它设计成不变类。
参考资料