个人博客
http://www.milovetingting.cn
原型模式
模式介绍
原型模式是一个创建型的模式。多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例,可使程序运行更高效。
模式定义
用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。
使用场景
类初始化需要消耗非常多的资源
 
通过new产生一个对象需要非常繁琐的数据准备或访问权限
 
一个对象需要提供给其它对象访问,而且各个调用者可能都需要修改值
 
通过实现Cloneable接口的原型模式在调用clone函数构造实例时,并不一定比通过new操作速度快,只有当通过new构造函数对象较为耗时或成本较高时,通过clone方法才能够获得效率上的提升。
简单实现
以简单的文档拷贝为例演示简单的原型模式。
先来演示浅拷贝
文档定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
   | public class Document implements Cloneable {
  	private String mText; 	private ArrayList<String> mImages = new ArrayList<>();
  	public String getmText() { 		return mText; 	}
  	public void setmText(String mText) { 		this.mText = mText; 	}
  	public List<String> getmImages() { 		return mImages; 	}
  	public void addImage(String image) { 		mImages.add(image); 	}
  	public void showDocument() { 		System.out.println(this); 	}
  	@Override 	protected Object clone() throws CloneNotSupportedException { 		Document doc = (Document) super.clone(); 		doc.mText = this.mText; 		doc.mImages = this.mImages; 		return doc; 	}
  	@Override 	public String toString() { 		return "Document [mText=" + mText + ", mImages=" + mImages + "]"; 	}
  }
  | 
 
调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | public static void main(String[] args) { 		Document doc1 = new Document(); 		doc1.setmText("文档1"); 		doc1.addImage("图片1"); 		doc1.showDocument(); 		Document doc2; 		try { 			doc2 = (Document) doc1.clone(); 			doc2.setmText("文档2"); 			doc2.addImage("图片2"); 			doc2.showDocument(); 			doc.showDocument(); 		} catch (CloneNotSupportedException e) { 			e.printStackTrace(); 		}
  	}
  | 
 
创建文档1,然后显示文档1的内容。然后拷贝了文档1,修改了文档1的内容,然后依次显示文档2,文档1
输出结果
1 2 3
   | Document [mText=文档1, mImages=[图片1]] Document [mText=文档2, mImages=[图片1, 图片2]] Document [mText=文档1, mImages=[图片1, 图片2]]
   | 
 
可以看到,修改拷贝后的文档2的Text,文档1没有受影响,但是修改文档2的Images,文档1也被修改了。
下面演示深拷贝
只需要修改clone方法
1 2 3 4 5 6 7 8 9
   | @SuppressWarnings("unchecked") 	@Override 	protected Object clone() throws CloneNotSupportedException { 		Document doc = (Document) super.clone(); 		doc.mText = this.mText; 		 		doc.mImages = (ArrayList<String>) this.mImages.clone(); 		return doc; 	}
  | 
 
再次运行后的输出结果:
1 2 3
   | Document [mText=文档1, mImages=[图片1]] Document [mText=文档2, mImages=[图片1, 图片2]] Document [mText=文档1, mImages=[图片1]]
   | 
 
修改文档2的Images并没有影响到文档1。
小结
原型模式本质上就是对象拷贝,容易出现的问题是深拷贝、浅拷贝。使用原型模式可以解决构建复杂对象的资源消耗问题,能够在某些场景下提升创建对象的效率。还有一个重要用途是保护性拷贝,也就是某个对象对外可能是只读的,为了防止外部对这个只读对象修改,可以通过返回一个对象拷贝的形式来实现只读的限制。