在阎宏博士的《JAVA与模式》一书中开头是这样描述不变(Immutable)模式的:

  一个对象的状态在对象被创建之后就不再变化,这就是所谓的不变模式。


不变模式的结构

  不变模式可增强对象的强壮型(robustness)。不变模式允许多个对象共享某一个对象,降低了对该对象进行并发访问时的同步化开销。如果需要修改一个不变对象的状态,那么就需要建立一个新的同类型对象,并在创建时将这个新的状态存储在新对象里。

  不变模式只涉及到一个类。一个类的内部状态创建后,在整个生命周期都不会发生变化时,这样的类称作不变类。这种使用不变类的做法叫做不变模式。不变模式有两种形式:一种是弱不变模式,另一种是强不变模式。

 弱不变模式

  一个类的实例的状态是不可改变的;但是这个类的子类的实例具有可能会变化的状态。这样的类符合弱不变模式的定义。要实现弱不变模式,一个类必须满足下面条件:

  第一、所考虑的对象没有任何方法会修改对象的状态;这样一来,当对象的构造函数将对象的状态初始化之后,对象的状态便不再改变。

  第二、所有属性都应当是私有的。不要声明任何的公开的属性,以防客户端对象直接修改任何的内部状态。

  第三、这个对象所引用到的其他对象如何是可变对象的话,必须设法限制外界对这些可变对象的访问,以防止外界修改这些对象。如何可能,应当尽量在不变对象内部初始化这些被引用的对象,而不要在客户端初始化,然后再传入到不变对象内部来。如果某个可变对象必须在客户端初始化,然后再传入到不变对象里的话,就应当考虑在不变对象初始化的时候,将这个可变对象复制一份,而不要使用原来的拷贝。

  弱不变模式的缺点是:

  第一、一个弱不变对象的子对象可以是可变对象;换言之,一个弱不变对象的子对象可能是可变的。

  第二、这个可变的子对象可能可以修改父对象的状态,从而可能会允许外界修改父对象的状态。

 强不变模式

  一个类的实例不会改变,同时它的子类的实例也具有不可变化的状态。这样的类符合强不变模式。要实现强不变模式,一个类必须首先满足弱不变模式所要求的所有条件,并且还有满足下面条件之一:

  第一、所考虑的类所有的方法都应当是final,这样这个类的子类不能够置换掉此类的方法。

  第二、这个类本身就是final的,那么这个类就不可能会有子类,从而也就不可能有被子类修改的问题。

 “不变"和"只读"的区别

  "不变"(Immutable)与"只读"(Read Only)是不同的。当一个变量是”只读“时,变量的值不能直接改变,但是可以在其他变量发生改变的时候发生改变。

  比如,一个人的出生年月日是”不变“属性,而一个人的年龄便是”只读“属性,不是”不变“属性。随着时间的变化,一个人的年龄会随之发生变化,而人的出生年月日则不会变化。这就是”不变“和“只读”的区别。

不变模式在JAVA中的应用

  不变模式在JAVA中最著名的应用便是java.lang.String类。String类是一个强不变类型,在出现如下的语句时:

        String a = "test";
String b = "test";
String c = "test";

  JAVA虚拟机其实只会创建这样一个字符串的实例,而这三个String对象都在共享这一个值。

不变模式的优点和缺点

  不变模式有很明显的优点:

  (1)因为不能修改一个不变对象的状态,所以可以避免由此引起的不必要的程序错误;换言之,一个不变的对象要比可变的对象更加容易维护。

  (2)因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以自由地被不同的客户端共享。

  不变模式的缺点:

  不变模式唯一的缺点是:一旦需要修改一个不变对象的状态,就只好创建一个新的同类对象。在需要频繁修改不变对象的环境里,会有大量的不变对象作为中间结果被创建出来,再被JAVA垃圾收集器收集走。这是一种资源上的浪费。

  在设计任何一个类的时候,应当慎重考虑其状态是否有需要变化的可能性。除非其状态有变化的必要,不然应当将它设计成不变类。

《JAVA与模式》之不变模式的更多相关文章

  1. <代码整洁之道>、<java与模式>、<head first设计模式>读书笔记集合

    一.前言                                                                                       几个月前的看书笔记 ...

  2. java Future模式

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  3. 《java与模式》

    2012年3月 随笔档案 - java_my_life - 博客园--此网友 12年的博客都是和模式有关的,希望可以多看看.http://www.cnblogs.com/java-my-life/ar ...

  4. java与模式读后总结

    一 老规则边看边写书上的代码,磨磨蹭蹭三个多星期终于把一本1000+的java与模式看完了. 于是,在这里贴上自己对每个模式的思考和总结,其实这个东西在我边看边写的时候已经写了一大半,博文再写一次算是 ...

  5. 《JAVA与模式》之观察者模式

    转自:http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html 在阎宏博士的<JAVA与模式>一书中开头是这样 ...

  6. JAVA的模式对话框和非模式对话框

    周末的时候,一位网友让我帮他把他的无模式对话框改成有模式对话框. 界面是由swing制作的,都是JFrame,我从来没有接触过swing编程.大致的代码还是看的懂,很多都和C#很相似. 然后就去查资料 ...

  7. java工厂模式

    (1)概念大白话:java工厂模式就是客户端(main函数)要创建对象觉得麻烦就让另外一个叫工厂的类帮它创建,然后自己每次要创建对象就叫工厂帮它弄,举个例子,在没有工厂这个"手下" ...

  8. 《JAVA与模式》之单例模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述单例模式的: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的 ...

  9. Java代理模式

    java代理模式及动态代理类 1.      代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目 ...

随机推荐

  1. Java数据结构和算法(二)顺序存储的树结构

    Java数据结构和算法(二)顺序存储的树结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 二叉树也可以用数组存储,可以和完 ...

  2. AMD、CMD、UMD 模块的写法

    简介 最近几年,我们可以选择的Javascript组件的生态系统一直在稳步增长.虽然陡增的选择范围是极好的,但当组件混合匹配使用时就会出现很尴尬的局面.开发新手们会很快发现不是所有组件都能彼此“和平相 ...

  3. tomcat中如何配置虚拟路径

    第一步:打开server.xml配置文件.在Host节点里写上该行代码: <Context path="/upload" docBase="E:\upload&qu ...

  4. idea中实体类序列化后生成序列化版本ID的方法

    为什么要添加序列化版本ID了(serialVersionUID)? 通过判断实体类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVers ...

  5. 关闭父类弹出的ifream窗口

    parent.document.getElementById('zhuce').style.display = 'none';

  6. 集合(四)HashMap

    之前的List,讲了ArrayList.LinkedList,最后讲到了CopyOnWriteArrayList,就前两者而言,反映的是两种思想: (1)ArrayList以数组形式实现,顺序插入.查 ...

  7. leetcode-爬楼梯(动态规划)

    假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: 2 解释: 有两 ...

  8. Android-BitmapUtil工具类

    Bitmap工具类,获取Bitmap对象 public class BitmapUtil { private BitmapUtil(){} /** * 根据资源id获取指定大小的Bitmap对象 * ...

  9. 使用Markdown语法画流程图

    Markdown流程图   鉴于本人使用的是马克飞象,所以一下以马克飞象为例: 语法   流程图的画法和代码块类似,流程图也是写在两个```之间的.格式用flow表示,例如: st=>start ...

  10. 关于Java_Web连接Oracle数据库

    1.前提条件 1>装有Oracle数据库(因为连接的时候需要开启两项服务) 2>myeclipse或eclipse(支持WebProject的版本)开发环境,本机以myeclipse为例, ...