定义
原型模式(Prototype Pattern)是设计模式的一种,它是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的初始化数据。
UML图
- 客户端(Client)角色:客户端提出创建对象的请求。
- 抽象原型(Prototype)角色:通常由一个Java接口或者Java抽象类来实现。从而为具体原型设立好规范。
- 具体原型(Concrete Prototype)角色:被复制的具体对象,此具体角色实现了抽象原型角色所要求实现的方法。
深入分析
原理:
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
Java在语言级别是自己支持原型模式的。我们知道,在java.lang.Object是一切类和接口的父类,而java.lang.Object正好提供了一个clone()方法来支持原型模式。当然,一个对象如果想具有被复制的能力,还必须声明自己实现了Cloneable接口,如果没有声明,就会在对象被复制的时候抛出CloneNotSupportedException。
在java.lang.Object中提供了一个 protected Object clone() 方法来支持对象的克隆,子类可以采用默认的方式进行所有字段的复制,也可以在子类中覆盖clone()方法,根据实际需要定制自己的复制行为。
复制有浅复制和深复制之分,浅复制是对基本数据类型和String类型而言的,深复制是对其他类型而言的。对于深复制,每一个应用也需要声明Cloneable接口。
原型模式使用场景和代码实现
package Prototype;
import java.util.ArrayList;
import java.util.List;
/**
* 肉麻情话类
* @author stoneWang_L
*/
public class SweetWord implements Cloneable {
//肉麻情话句子
private String content;
//肉麻情话句子集合
private List<String> contents;
/**
* 获取肉麻情话集合
* @return
*/
public List<String> getContents() {
return contents;
}
/**
* 设置肉麻情话集合
* @param contents
*/
public void setContents(List<String> contents) {
this.contents = contents;
}
/**
* 获取肉麻情话
* @return
*/
public String getContent() {
return content;
}
/**
* 设置肉麻情话
* @param content
*/
public void setContent(String content) {
this.content = content;
}
public SweetWord clone() {
try {
//新建一个肉麻情话对象,同时复制基本的属性
SweetWord sweetWord = (SweetWord) super.clone();
//新建一个肉麻情话集合
List<String> newContents = new ArrayList<String>();
//把原对象的肉麻情话集合中的肉麻情话集合通过forEach循环加入新建的newContents中
for(String friend : this.getContents()) {
newContents.add(friend);
}
//把新的肉麻情话集合设置进新的对象
sweetWord.setContents(newContents);
//返回新的肉麻情话对象
return sweetWord;
} catch(CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
package Prototype;
import java.util.ArrayList;
import java.util.List;
public class PrototypeClient {
public static void main(String[] args) {
//新建一个肉麻情话对象并设置相应的属性
SweetWord content1 = new SweetWord();
List<String> contents = new ArrayList<String>();
contents.add("宝贝,我爱你");
contents.add("你是我的唯一");
content1.setContents(contents);
//复制content1
SweetWord content2 = content1.clone();
//分别输出两个对象的内容
System.out.println(content1.getContents());
System.out.println(content2.getContents());
//在原来的肉麻情话对象中加入新的内容并把新的内容设置进去
contents.add("你是我的真命天女");
content1.setContents(contents);
//分别输出新的修改后的两个肉麻情话对象
System.out.println(content1.getContents());
System.out.println(content2.getContents());
}
}
原型模式的优缺点
优点
1、允许动态地增加或减少产品类。由于创建产品类实例的方法是产品类内部具有的,因此增加新产品对整个结构没有影响。
2、提供简化的创建结构。
3、具有给一个应用软件动态加载新功能的能力。
4、产品类不需要非得有任何事先确定的等级结构,因为原型模式适用于任何的等级结构。
缺点
每一个类都必须配备一个克隆方法,这对于全新的类来说不是很难,而对于已有的类来说实现clone()方法不一定很容易,而且在进行比较深层次的复制的时候也需要编写一定工作量的代码。
原型模式的实际应用简介
原型对象一般适用于以下场景:
在创建对象的时候,我们不仅希望被创建的对象继承其类的基本机构,而且还希望继承原型对象的数据。
希望对目标对象的修改不印象既有的原型对象(深度克隆的时候可以完全互相不影响)。
隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。