不可变种(immutable class)
不可变类(immutable class)不可变类,顾名思义就是说类的实例是不可被修改的。实例的信息是在创建的时候提供
不可变类(immutable class)
不可变类,顾名思义就是说类的实例是不可被修改的。实例的信息是在创建的时候提供,并且在整个生命周期中都不可改变。
大家都知道Java的String类是immutable。其实primary的包装类都是immutable的。那么如果让你设计和immutable的class要怎么做呢?
immutable 也就是不变的意思。不可改变的。怎么样让一个类的对象不变呢?
第一你肯定想到,这个类不能被继承,于是class 前面要加 final。这是最直接的办法,也是最简单的办法,但是当你将来想对它扩展的时候就做不到了。也许你想在他的基础上定义一个子类也是immutable的。这时候你可以不再class 前面加final,而是在所有的方法上加final,同样可以防止子类重写它的方法。其实不用继承一样可以扩展这个类,通过composite方法。所以不推荐允许继承immutable类。另外,还有一个办法让immutable类不能被继承,那就是将方法私有或者protected也即是保内私有,然后提供一个静态工厂方法来生产实例。这是最推荐的方法,因为这个方法允许包内扩展,对客户类来说是不可继承的。同时静态工厂方法还有许多其他比构造方法好的地方。
第二你也可能会想到属性不能被改变,那field前面也得加final。你还得把属性私有化,防止被直接访问修改。这样就够了吗?那如果有一个其他类的对象的引用属性呢?怎么保证它不被变?
首先你能做到的就是保证自己的方法里面不改变它的值。然后怎么保证别的类不直接改变它呢?这个引用如果是别的对象传给你的呢?怎么保证不变? 同样,如果是方法中要返回这个属性呢?想想看。
如果它也是immutable的自然也就省心了。但如果不是呢?
看来必须得clone一个新的对象了。关于clone,可以参考liuwang126的文章http://liuwang126.iteye.com/blog/272595
下面是完整的Sample。
package client;import immutable.ClassA;import immutable.Immutable;class Client{public static final Immutable A = Immutable.getImmutable(1, new ClassA(1));public static final Immutable B = Immutable.getImmutable(2, new ClassA(2));}当然你也可以为Immutable 类提供一个静态工厂,由工厂来保证不会创建重复的对象实例。
这样也就节省了内存消耗和垃圾回收负担。如果你有这样的对象,在系统中会被大量的,频繁的,并发的读。不放考虑这种模式。其实String就是一个很好的例子。
很好的构建基石:你应该比较常用到Set和Map,尤其是map的key值,你是否经常需要考虑这些值会不会在你不经意间变了呢?从而使得影响你设定这个set或map的本意。如果用Immutable对象你就不用担心了吧?这样是为什么你总喜欢用String做key值。当然你也可能想尽量避免重写equals和hashCode方法。
不要滥用这种模式凡是必然是有利有弊。你知道immutable的对象会因为值的不同而生产新的对象,所以你要谨慎设计你的对象和使用方法。比如String,当你在循环里面连接字符串的时候就不建议你用String的+号,而是用BufferString,StringBuffer类用来表示内容可变的字符串,并提供了修改底层字符串的方法。当我们进行字符拼接时,请使用StringBuffer类而非String类,因为前者将比后者快上百倍。这也许也可以知道我们平衡我自己的设计。没准你也可以设计一个immutable类的伙伴(companion)类。
在我看来,当你想设计一种有结构的常量的时候,你可以考虑设计出一个immutable的类。
1 楼 fastwei 2011-02-24 都说的什么东东,标题党呀。 2 楼 tsxm 2011-02-25 可惜讲的太少了,就得calendar好像也是不可变类 3 楼 superheizai 2011-02-25 貌似不用final类吧,私有构造就可以使它不能被继承。 4 楼 JackyCheng2007 2011-02-25 superheizai 写道貌似不用final类吧,私有构造就可以使它不能被继承。
因为不提供修改对象参数的方法,如果把构造私有了,怎么生成这样一个对象呢?还要提供一个代替构造函数的一个工厂方法?
感觉语义上没有final类来的直接。 5 楼 yeak2001 2011-02-26 这样就够了吗?那如果有一个其他类的对象的引用属性呢?怎么保证它不被变?
对于这种情况你可以尝试change reference object to value object 6 楼 zhaspe 2011-02-27 其实关于immutable的概念和要点,楼主基本都写出来了,只是感觉写的有些抽象,让人不想看,其实楼主把要点1234的列出来就明显的多了