Immutable-不变模式与不变类
-
不变模式的定义
一个对象在创建之后就不再变化,就是所谓的不变模式(Immutable Pattern);
一般来讲,一个对象要么就是可变对象(Mutable Object),要么就是不变模式(Immutable Object);
- 不变模式的结构
不变模式可增强对象的强壮性。不变模式允许多个对象共享某个对象,降低了对该对象进行并发访问(Concurrent Access)时的同步化开销。如果需要修改一个对象,就需要建立一个新的同类型对象,并在创建时将这个新的状态存储在新对象里。
不变模式只涉及到一个类。一个类的内部状态创建后,在整个生命周期都不会发生变化,这样的类称为不变类。这样使用不变类的模式叫做不变模式。不变模式不需要类图。
不变模式有两种形式:弱不变模式和强不变模式。它们的区别是子类是否是不变的,强不变类都是final的。
不变和只读的区别:当一个变量是只读时,当一个变量是只读时,变量的值不能直接改变,但是可以在其他变量改变的时候跟着改变。例如:生日是不变的,年龄是只读的。
- 不变模式在JDK中的应用
(1)String是一个强不变类。例如:String a = "hello",String b = "hello",java虚拟机其实只会创建一个字符串的实例,而这两个String对象都在共享这一个值,所以a == b 是成立的。如果字符串内容频繁变化,就不宜使用String类型,应该使用StringBuffer类型,StringBuilder类型。
(2)封装类,即8个原始类型的封装类(Integer、Float、 Double、Byte、Long、Short、Boolean、Character)都是强不变类。
- 不变模式的优缺点
(1)因为不能修改一个不变对象的状态,所以可以避免由此引起的不必要的程序错误;换言之,一个不变对象要比可变对象更加容易维护。
(2)因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以自由地被不同的客户端共享。
(3)不需要保护性拷贝(Deffensive Copy)。
(4)不需要拷贝构造函数和clone。
(5)只计算一次hashcode。mutable object必须每次计算。
(6)不变模式的唯一的缺点是,一旦需要修改一个不变对象的状态,就只好创建一个新的同类对象。在需要频繁修改不变对象的环境里,会有大量的不变对象作为中间结果被创建出来,再被Java语言的垃圾收集器收集走,这是一种资源上的浪费。
在设计任何一个类的时候,应当慎重考虑其状态是否有需要变化的可能性。除非其状态有变化的必要,不然应当将它设计成不变类。
- 自定不变类注意点
不提供setter
设置类为final,使其不被子类化。
设置所有成员变量(域)为final和private,防止直接修改。
如果某些成员变量是immuable的,那这些变量一定不能被外界访问到。如果要访问,要使用保护性拷贝来复制一份传给外界。