原型模式的定义: 原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些
原型创建新的对象。原型模式是一种对象创建型模式。需要注意的是通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,通常对克隆所产生的对象进行修改对原型对象不会造成任何影响,每一个克隆对象都是相互独立
的
例:
/**
* Person
*/
public class Person implements Cloneable{
private String name;
private int age;
private String sex;
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @param sex the sex to set
*/
public void setSex(String sex) {
this.sex = sex;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the sex
*/
public String getSex() {
return sex;
}
public Person clone() {
Person person = (Person) super.clone();
return person;
}
public void println() {
System.out.println("name is :" + name);
System.out.println("age is :" + age);
System.out.println("sex is :" + sex);
}
}
注:能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个Java类支持被
复制。如果一个类没有实现这个接口但是调用了clone()方法,Java编译器将抛出一个
CloneNotSupportedException异常。
通过调用person 类的clone方法可以返回一个新的得对象,但上面的方法属于浅克隆,遇到引用类型的就没法克隆了,就需要重新手动创建
例:
import java.util.ArrayList;
import java.util.List;
/**
* Person
*/
public class Person implements Cloneable{
private String name;
private int age;
private String sex;
private List<String> firends = new ArrayList<>();
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @param sex the sex to set
*/
public void setSex(String sex) {
this.sex = sex;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the sex
*/
public String getSex() {
return sex;
}
/**
* @param firends the firends to set
*/
public void setFirends(List<String> firends) {
this.firends = firends;
}
/**
* @return the firends
*/
public List<String> getFirends() {
return firends;
}
public void addFirend(String f) {
firends.add(f);
}
public Person clonePerson() {
Person person = Person(super.clone());
// 深度克隆
List<String> f = firends.subList(0, firends.size());
person.setFirends(f);
return person;
}
public void println() {
System.out.println("name is :" + name);
System.out.println("age is :" + age);
System.out.println("sex is :" + sex);
System.out.println("firends is :" + firends.toString());
}
}
原型模式总结:
1.主要优点
原型模式的主要优点如下:
(1) 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个
已有实例可以提高新实例的创建效率。
(2) 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编
程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。
(3) 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的
工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的
克隆方法实现的,无须专门的工厂类来创建产品。
(4) 可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起
来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。
2.主要缺点
原型模式的主要缺点如下:
(1) 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进
行改造时,需要修改源代码,违背了“开闭原则”。
(2) 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了
实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。
3.适用场景 在以下情况下可以考虑使用原型模式:
(1) 创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资
源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对
其成员变量稍作修改。
(2) 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占用内存较少时,可
以使用原型模式配合备忘录模式来实现。
(3) 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的
几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方
便。