什么是 Immutable Object
Immutable Object 模式是一种将对象设计为一旦创建就不能修改其属性值,所有的属性值都只有 getter 方法没有 setter 方法的模式。
该模式有两种实现途径:一是在构造方法中提供所有属性的参数,设置好所有的属性值;二是提供 builder 方法来让用户逐步设置属性值,最后再创建对象实例。前者是作者写起来省事,但用起来麻烦点;后者则是用起来省事,而作者写起来麻烦点。
Immutable Object 的优点
一个不能修改属性值的对象有什么优点呢?首先它是线程安全的,而且多个线程对它的访问不需要有任何同步操作,因此不会对线程的运行效率产生任何影响。
其次是在某些场景下,使用 Immutable Object 这种保守的封装方式能避免一些问题的发生。
举个例子。HttpClient 通过配置对象来进行初始化,而这个配置对象是调用者给过来的,这意味着调用者可能会继续持有该对象,甚至在 HttpClient 的运行过程中还会试图修改其属性。
这么做是存在比较严重的问题的。首先,这些修改有可能是无效的,因为一旦完成初始化,它的一些属性就不会再用到了;其次,有些修改可能会导致并发问题,因为配置对象是会被多线程访问的;再次,只有初始化过程会对配置属性进行检查,如果一个属性在这之后被修改成了一个无效的值,这会导致故障的发生。
所以,将配置对象设计为 Immutable Object,能避免上面所说的问题,极大的提高应用的健壮性。
避免滥用 Immutable Object
但如果一个对象不存在上面所说的使用场景,那么就不需要将其设计为 Immutable Object。典型的例子就是 DTO 对象,这类对象的职责仅仅是传递数据,其生命周期很短,甚至在方法执行完后就马上失去任何引用,可以被回收了。
对 DTO 对象的属性进行修改不会引发任何问题。因为作为传递对象,发送方只会写,接收方只会读,并不需要做特别的限制。
更重要的是,DTO 对象是一定有序列化和反序列化的要求的,这是它的一个天然职责,Immutable Object 因为缺少 setter 方法,会让所有依赖 setter 方法进行反序列化的框架无法正常运作。所以 Immutable Object 不适合用在 DTO 类上。
补充(2020-09-14):现在我觉得 DTO 对象可以使用 Immutable Object,因为这么做对 GC 有好处。唯一需要解决的就是反序列化问题。
总之,我们在对一个类应用特别的设计模式时,最好先考虑清楚这个设计模式的目的和适用场景,这个类是否符合这个场景。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。