原型模式
动机or背景
- 在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求变化,这些对象经常面临着剧烈的变化,但是他们呢却拥有比较稳定一致的接口。
- 如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?
模式定义
使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
结构
举例
学习过程中没找到很好的例子,下面我从网上找了两个例子。
例子一:
#include <iostream>
#include <string>
using namespace std;
class Prototype
{
private:
string str;
public:
Prototype(string s)
{
str = s;
}
Prototype()
{
str = "";
}
void show()
{
cout << str << endl;
}
virtual Prototype *clone() = 0;
};
class ConcretePrototype1 :public Prototype
{
public:
ConcretePrototype1(string s) :Prototype(s)
{}
ConcretePrototype1(){}
virtual Prototype *clone()
{
ConcretePrototype1 *p = new ConcretePrototype1();
*p = *this;
return p;
}
};
class ConcretePrototype2 :public Prototype
{
public:
ConcretePrototype2(string s) :Prototype(s)
{}
ConcretePrototype2(){}
virtual Prototype *clone()
{
ConcretePrototype2 *p = new ConcretePrototype2();
*p = *this;
return p;
}
};
int main()
{
ConcretePrototype1 *test = new ConcretePrototype1("小李");
ConcretePrototype2 *test2 = (ConcretePrototype2 *)test->clone();
test->show();
test2->show();
return 0;
}
例子二:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string _name, int _age) :name(_name), age(_age) {}
virtual ~Person() {}
virtual void showMe()
{
cout << "I am " << name << ", and " << age << endl;
}
virtual Person *clone()
{
return new Person(*this);
}
};
class Boy :public Person
{
public:
Boy(string _name, int _age):Person(_name, _age)
{}
~Boy() {}
virtual void showMe() override
{
Person::showMe();
cout << "I am a boy" << endl;
}
virtual Person *clone() override
{
return new Boy(*this);
}
};
class Girl :public Person
{
public:
Girl(string _name, int _age) :Person(_name, _age)
{}
~Girl() {}
virtual void showMe() override
{
Person::showMe();
cout << "I am a Girl" << endl;
}
virtual Person *clone() override
{
return new Girl(*this);
}
};
int main()
{
//创建一个boy a
Person *a = new Boy(string("Ming"), 28);
a->showMe();
//创建一个Girl b
Person *b = new Girl(string("Li"), 28);
b->showMe();
//克隆a--不使用原型模式的写法
shared_ptr<Person> cloneA(new Boy(*dynamic_cast<Boy *>(a)));
cloneA->showMe();
//克隆b--使用原型模式的写法
shared_ptr<Person> cloneB(b->clone());
cloneB->showMe();
delete b;
delete a;
return 0;
}
要点总结
- Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。
- Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象–所需工作仅仅是注册一个新类的对象(即原型),然后再任何需要的地方Clone。
- Prototype模式中Clone方法可以利用某些框架中的序列化来实现深拷贝。