原型模式通过给出一个原型对象来指明所要创建对象的类型,然后克隆该原型对象以便创建出更多同类型的新对象
主要执行克隆操作,实现创建新的对象
适用性
1.当一个系统应该独立于它的产品创建、构成和表示时。
2.当要实例化的类是在运行时刻指定时,例如,通过动态装载。
3.为了避免创建一个与产品类层次平行的工厂类层次时。
4.当一个类的实例只能有几个不同状态组合中的一种时。
建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
假 设一个系统的产品类是动态加载的,而且产品类具有一定的等极结构。这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级。而产品类的等级结构 一旦变化,工厂类的等级结构就不得不有一个相应的变化。这对于产品结构可能会有经常性变化的系统来说,采用工厂模式就有不方便之处。
这时如果采取原型模式,给每一个产品类配备一个克隆方法(大多数的时候只需给产品类等级结构的基类配备一个克隆方法),便可以避免使用工厂模式所带来的具有固定等级结构的工厂类。
原型模式是浅克隆,clone方法实现的复制是“浅拷贝”(浅克隆),也就是说克隆的不够彻底,被克隆出的对象中的变量和原来的对象中的变量有相同的值,但是克隆出的对象中的引用和原对象中的引用的指向是相同的,但是克隆出的对象等同new是新的物理地址
因此,使用原型模式克隆出的对象,物理地址是新的(clon==clon2 为 false),使用’==’比较两个对象的class类型(clon.getClass()==clon2.getClass())都是一样的为true,克隆出的对象中的引用和原对象中的引用的指向是相同的clon.getSub()==clon2.getSub() 为 true
原型对象的数据和克隆出的对象数据变化:
由于是浅克隆,所以当原型中的属性值变化时,被克隆对象的属性值是不变的(参考浅克隆案例),但如果原型中的引用对象发生变化,被克隆出的对象中的引用对象也会发生改变,因为克隆的不彻底,如果需要被克隆出的对象中的引用对象不变,就需要用深克隆实现(具体参考深克隆案例)
运用:
假 设一个系统的产品类是动态加载的,而且产品类具有一定的等极结构,这时使用原型模式比工厂模式更方便
https://www.2cto.com/kf/201212/172624.html这个链接对于克隆讲的比较详细
代码示例:
public class Prototype {
public static void main(String[] args) {
Clon clon = new Clon();
clon.setStr("helloworld");
Clon clon2 = (Clon) clon.clone();
System.out.println("clon.getClass()==clon2.getClass() ? "
+ (clon.getClass() == clon2.getClass()));
System.out.println("clon==clon2 ? " + (clon == clon2));
System.out.println("clon.getSub()==clon2.getSub() ? "
+ (clon.getSub() == clon2.getSub()));
System.out.println(clon.equals(clon2));
}
}
class Clon implements Cloneable {
private String str = null;
private substance sub = new substance();
public void setStr(String str) {
this.str = str;
}
public substance getSub() {
return sub;
}
public void printStr() {
System.out.println(str);
}
public Object clone() {
Clon to_clon = null;
try {
to_clon = (Clon) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e);
} finally {
return to_clon;
}
}
}
class substance {
}
深克隆代码示例:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
//深克隆
public class CloneObject
{
/**
* 克隆对象
*/
public static Object deepClone(Object src)
{
Object o = null;
try
{
if (src != null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(src);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
o = ois.readObject();
ois.close();
}
}
catch (IOException e)
{
//LOG.error("ServiceOper Occur an Exception when deepClone", e);
}
catch (ClassNotFoundException e)
{
//LOG.error("ServiceOper Occur an Exception when deepClone", e);
}
return o;
}
public static void main(String[] args)
{
UserInfo u1 = new UserInfo();
u1.setUserName("I'm u1");
UserInfo u2 = (UserInfo)deepClone(u1);
System.out.println(u2.getUserName());
}
}
//该类实现序列化接口
class UserInfo implements Serializable
{
private static final long serialVersionUID = 1L;
private String userName;
private String age;
public String getUserName(){
return userName;
}
public void setUserName(String userName){
this.userName = userName;
}
public String getAge(){
return age;
}
public void setAge(String age){
this.age = age;
}
}