简介
用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
什么情况下使用原型设计模式呢?
一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
实现方式
- c++
c++中可以通过实现拷贝构造函数的方法实现,要注意深拷贝和浅拷贝的问题。 - java
- 实现Cloneable接口,并覆写clone方法;
- 使用对象流。使用对象流,所有的自定义类型需要实现Serializable接口。
抽象原型
class Prototype {
public:
virtual Prototype * clone() = 0;
};
具体原型
class ContretePrototype :public Prototype {
private:
char *name;
int id;
public:
ContretePrototype(const char *name, int id) {
this->name = NULL;
if (name != NULL) {
//this->name = (char *)malloc(sizeof(char)*(strlen(name) + 1));
this->name = new char[sizeof(char)*(strlen(name) + 1)];
strcpy(this->name, name);
}
this->id = id;
}
ContretePrototype(const ContretePrototype& prototype) {
this->name = NULL;
if (prototype.getName() != NULL) {
this->name = (char *)malloc(sizeof(char)*(strlen(prototype.getName()) + 1));
strcpy(this->name, prototype.getName());
}
this->id = prototype.getId();
}
Prototype * clone() {
ContretePrototype *prototype = new ContretePrototype(*this);
return prototype;
}
~ContretePrototype() {
if (this->name != NULL) {
//free (this->name);
delete[]this->name;
}
}
int getId()const {
return this->id;
}
char * getName()const {
return this->name;
}
};
测试
int main()
{
ContretePrototype p("abc", 1);
cout << p.getName() << " " << p.getId() << endl;
ContretePrototype *p1 =dynamic_cast<ContretePrototype *>( p.clone());
cout << p1->getName() << " " << p1->getId() << endl;
delete p1;
return 0;
}
Java版
public class A implements Cloneable,Serializable {
private int x;
private int y;
public A(int x, int y) {
this.x = x;
this.y = y;
}
@Override
protected Object clone() {
Object o=null;
try {
o=(A)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "A{" +
"x=" + x +
", y=" + y +
'}';
}
}
public class Prototype implements Cloneable, Serializable {
private List<A> list;
private A a;
private int id;
private String name;
@Override
protected Object clone() {
Prototype o = null;
try {
o = (Prototype) super.clone();
o.setA((A) o.getA().clone());
List<A> temp = new ArrayList<A>(o.getList().size());
for (A a : o.getList()) {
temp.add((A) a.clone());
}
o.setList(temp);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
public Object deepClone() throws IOException, ClassNotFoundException {
//将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
public List<A> getList() {
return list;
}
public void setList(List<A> list) {
this.list = list;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Prototype{" +
"list=" + list +
", a=" + a +
", id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//构造对象
Prototype prototype = new Prototype();
List<A> list = new ArrayList<A>();
A a1 = new A(1, 2);
A a2 = new A(10, 20);
list.add(a1);
list.add(a2);
prototype.setList(list);
A a3 = new A(100, 200);
prototype.setA(a3);
prototype.setId(1000);
prototype.setName("prototype name");
//打印对象内容
log(prototype.toString());
//使用clone克隆
Prototype p1 = (Prototype) prototype.clone();
//查看克隆后的结果
log(p1.toString());
//使用对象流序列化
Prototype p2 = (Prototype) p1.deepClone();
p1.getA().setX(300);
p1.getList().get(0).setX(3000);
log(prototype.toString());
log(p2.toString());
}
public static void log(String content) {
System.out.println(content);
}
}
结果
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Process finished with exit code 0