
C++ 原型模式讲解和代码示例
原型是一种创建型设计模式, 使你能够复制对象, 甚至是复杂对象, 而又无需使代码依赖它们所属的类。
所有的原型类都必须有一个通用的接口, 使得即使在对象所属的具体类未知的情况下也能复制对象。 原型对象可以生成自身的完整副本, 因为相同类的对象可以相互访问对方的私有成员变量。
复杂度:
流行度:
识别方法: 原型可以简单地通过 clone
或 copy
等方法来识别。
概念示例
本例说明了原型设计模式的结构并重点回答了下面的问题:
- 它由哪些类组成?
- 这些类扮演了哪些角色?
- 模式中的各个元素会以何种方式相互关联?
main.cc: 概念示例
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. If 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_map<Type, Prototype *, std::hash<int>> 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; }
Output.txt: 执行结果
Let's create a Prototype 1 Call Method from PROTOTYPE_1 with field : 90 Let's create a Prototype 2 Call Method from PROTOTYPE_2 with field : 10