“一成不变”的弊端

变类的建立似乎是一个好方案。但是,一旦真的需要那种新类型的一个修改的对象,就必须辛
苦地进行新对象的创建工作,同时还有可能涉及更频繁的垃圾收集。对有些类来说,这个问题并不是很大。
但对其他类来说(比如 String 类),这一方案的代价显得太高了。


为解决这个问题,我们可以创建一个“同志”类,并使其能够修改。以后只要涉及大量的修改工作,就可换
为使用能修改的同志类。完事以后,再切换回不可变的类。

/**
 * 同志类,它也含有 add() 和 multiply() 方法。但这些方法
 * 能够修改 Mutable 对象,而不是新建一个。除此以外, Mutable
 *  的一个方法可用它的数据产生一个Immutable2 对象,
 * @author lsj
 *
 */
class Mutable{
	private int data ;
	public Mutable (int initVal){
		data = initVal ;
	}
	
	public Mutable add(int x ){
		data += x ;
		return this ;
	}
	public Mutable multiply( int x ){
		data *= x ;
		return this;
	}
	public Imutable2 makeImutable2(){
		return new Imutable2(data) ;
	}
}
/**
 * 包含的方法保留了对象不可变的特征,只要涉及修改,就创建新的对象。
 * @author lsj
 *
 */
public class Imutable2 {
	private int data ;
	
	public Imutable2(int data) {
		this.data = data ;
	}
	public int read (){
		return data ;
	}
	public boolean nonzero (){
		return data!= 0;
	}
	public Imutable2 add (int x ){
		return new Imutable2(data+ x ) ;
	}
	public Imutable2 multiply(int x ){
		return new Imutable2(data*x); 
	}
	public Mutable makeMutable (){
		return new Mutable(data) ;
	}
	/**
	 * 在 modify1() 中,所有工作都是在 Immutable2 类中完成的,
	 * 我们可看到在进程中创建了四个新的 Immutable2 对象(而且每次
	 * 重新分配了val,前一个对象就成为垃圾)。
	 * @param y
	 * @return
	 */
	public static Imutable2 modify1 (Imutable2 y ){
		Imutable2 val = y.add(12) ;
		val = val.multiply(3);
		val = val.add(11) ;
		val = val.multiply(2);
		return val ;
	}
	//this get the same result 
	/**
	 * 在方法 modify2() 中,可看到它的第一个行动是获取 Immutable2 y,然后从中生成一个 Mutable(类似于前
	 * 面对 clone() 的调用,但这一次创建了一个不同类型的对象)。随后,用 Mutable 对象进行大量修改操作,
	 * 同时用不着新建许多对象。最后,它切换回 Immutable2。在这里,我们只创建了两个新对象(Mutable 和
	 * Immutable2 的结果),而不是四个。
	 * @param y
	 * @return
	 */
	public static Imutable2 modify2 (Imutable2 y){
		Mutable m = y.makeMutable() ;
		m.add(12).multiply(3).add(11).multiply(2) ;
		return m.makeImutable2() ;
	}
	
	public static void main (String [] args ){
		Imutable2 i2 = new Imutable2(47) ;
		Imutable2 r1 = modify1(i2) ;
		Imutable2 r2 = modify2(i2 );
		System.out.println(i2.read()) ;
		System.out.println(r1.read() );
		System.out.println(r2.read() );
	}

}

  

上面 的方法适合用于:

(1) 需要不可变的对象,而且
(2) 经常需要进行大量修改,或者
(3) 创建新的不变对象代价太高

  

原文地址:https://www.cnblogs.com/chuiyuan/p/4368575.html