1.原型模式(Prototype)
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
所有的原型类都必须有一个通用的接口, 使得即使在对象所属的具体类未知的情况下也能复制对象。 原型对象可以生成自身的完整副本, 因为相同类的对象可以相互访问对方的私有成员变量。
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。通俗的讲就是当需要创建一个新的实例化对象时,我们刚好有一个实例化对象,但是已经存在的实例化对象又不能直接使用。这种情况下拷贝一个现有的实例化对象来用,可能会更方便。
以下情形可以考虑使用原型模式:
当new一个对象,非常繁琐复杂时,可以使用原型模式来进行复制一个对象。比如创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。
当需要new一个新的对象,这个对象和现有的对象区别不大,我们就可以直接复制一个已有的对象,然后稍加修改。
当需要一个对象副本时,比如需要提供对象的数据,同时又需要避免外部对数据对象进行修改,那就拷贝一个对象副本供外部使用。
using std::string; // Prototype Design Pattern Intent: Lets you copy existing objects without making your code dependent on// their classes. enum Type { PROTOTYPE_1 = 0, PROTOTYPE_2 }; /** * The example class that has cloning ability. We'll see how the values of field * with different types will be cloned. */ class Prototype { protected: string prototype_name_; float prototype_field_; public: Prototype() {} Prototype(string prototype_name) : prototype_name_(prototype_name) { } virtual ~Prototype() {} virtual Prototype *Clone() const = 0; virtual void Method(float prototype_field) { this->prototype_field_ = prototype_field; std::cout << "Call Method from " << prototype_name_ << " with field : " << prototype_field << std::endl; } }; /** * ConcretePrototype1 is a Sub-Class of Prototype and implement the Clone Method * In this example all data members of Prototype Class are in the Stack. If you * have pointers in your properties for ex: String* name_ ,you will need to * implement the Copy-Constructor to make sure you have a deep copy from the * clone method */ class ConcretePrototype1 : public Prototype { private: float concrete_prototype_field1_; public: ConcretePrototype1(string prototype_name, float concrete_prototype_field) : Prototype(prototype_name), concrete_prototype_field1_(concrete_prototype_field) { } /** * Notice that Clone method return a Pointer to a new ConcretePrototype1 * replica. so, the client (who call the clone method) has the responsability * to free that memory. I you have smart pointer knowledge you may prefer to * use unique_pointer here. */ Prototype *Clone() const override { return new ConcretePrototype1(*this); } }; class ConcretePrototype2 : public Prototype { private: float concrete_prototype_field2_; public: ConcretePrototype2(string prototype_name, float concrete_prototype_field) : Prototype(prototype_name), concrete_prototype_field2_(concrete_prototype_field) { } Prototype *Clone() const override { return new ConcretePrototype2(*this); } }; /** * In PrototypeFactory you have two concrete prototypes, one for each concrete * prototype class, so each time you want to create a bullet , you can use the * existing ones and clone those. */ class PrototypeFactory { private: std::unordered_mapint>> prototypes_; public: PrototypeFactory() { prototypes_[Type::PROTOTYPE_1] = new ConcretePrototype1("PROTOTYPE_1 ", 50.f); prototypes_[Type::PROTOTYPE_2] = new ConcretePrototype2("PROTOTYPE_2 ", 60.f); } /** * Be carefull of free all memory allocated. Again, if you have smart pointers * knowelege will be better to use it here. */ ~PrototypeFactory() { delete prototypes_[Type::PROTOTYPE_1]; delete prototypes_[Type::PROTOTYPE_2]; } /** * Notice here that you just need to specify the type of the prototype you * want and the method will create from the object with this type. */ Prototype *CreatePrototype(Type type) { return prototypes_[type]->Clone(); } }; void Client(PrototypeFactory &prototype_factory) { std::cout << "Let's create a Prototype 1\n"; Prototype *prototype = prototype_factory.CreatePrototype(Type::PROTOTYPE_1); prototype->Method(90); delete prototype; std::cout << "\n"; std::cout << "Let's create a Prototype 2 \n"; prototype = prototype_factory.CreatePrototype(Type::PROTOTYPE_2); prototype->Method(10); delete prototype; } int main() { PrototypeFactory *prototype_factory = new PrototypeFactory(); Client(*prototype_factory); delete prototype_factory; return 0; } |
2.原型模式优缺点
优点 | 缺点 |
你可以克隆对象, 而无需与它们所属的具体类相耦合。 | 你可以用继承以外的方式来处理复杂对象的不同配置。 |
你可以克隆预生成原型, 避免反复运行初始化代码。 | |
你可以更方便地生成复杂对象。 |