簡介
用于創(chuàng)建重復(fù)的對象,同時又能保證性能霜定。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式廊鸥。這種模式是實現(xiàn)了一個原型接口望浩,該接口用于創(chuàng)建當(dāng)前對象的克隆。當(dāng)直接創(chuàng)建對象的代價比較大時惰说,則采用這種模式磨德。
什么情況下使用原型設(shè)計模式呢?
一個對象需要在一個高代價的數(shù)據(jù)庫操作之后被創(chuàng)建助被。我們可以緩存該對象剖张,在下一個請求時返回它的克隆切诀,在需要的時候更新數(shù)據(jù)庫揩环,以此來減少數(shù)據(jù)庫調(diào)用。
實現(xiàn)方式
- c++
c++中可以通過實現(xiàn)拷貝構(gòu)造函數(shù)的方法實現(xiàn)幅虑,要注意深拷貝和淺拷貝的問題丰滑。 - java
- 實現(xiàn)Cloneable接口,并覆寫clone方法;
- 使用對象流。使用對象流褒墨,所有的自定義類型需要實現(xiàn)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 {
//構(gòu)造對象
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");
//打印對象內(nèi)容
log(prototype.toString());
//使用clone克隆
Prototype p1 = (Prototype) prototype.clone();
//查看克隆后的結(jié)果
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);
}
}
結(jié)果
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