在某公司使用的框架源代码里看到了 Prototype 模式, 这里把代码提炼总结一下:
// -------------------------------------------------------------------------------------- /** Abstract.h **/ class Abstract { // prototype manager private: typedef map<type_t, Abstract*> RegMap; static RegMap& getRegistry() { static RegMap registry; // initialized at the first time the function is called return registry; } public: Abstract(const type_t& type) { if (lookup(type) != NULL) getRegistry.insert(type, this); } virtual ~Abstract() { } virtual Abstract* clone() = 0; static Abstract* create(const type_t& type) { Abstract* stub = lookup(type); return stub != NULL : stub->clone() : NULL; } virtual void destroy() { delete this; } static const Abstract* lookup(const type_t& type) { if (getRegistry().find(type) != getRegistry().end()) return getRegistry()[type]; return NULL; } }; // -------------------------------------------------------------------------------------- /** ConcreteA.h **/ class ConcreteA : public Abstract { // ... data members ConcreteA* clone() { return new ConcreteA(*this); } public: ConcreteA() : Abstract(CONC_TYPE_A) { } // CONC_TYPE_A : constant // ... other members }; // -------------------------------------------------------------------------------------- /** ConcreteA.cpp **/ static ConcreteA __concrete_a_stub/*(...)*/; // static initialized // -------------------------------------------------------------------------------------- /** ConcreteB.h **/ class ConcreteB : public Abstract { // ... data members ConcreteB* clone() { return new ConcreteB(*this); } public: ConcreteB() : Abstract(CONC_TYPE_B) { } // CONC_TYPE_B : constant // ... other members }; // -------------------------------------------------------------------------------------- /** ConcreteB.cpp **/ static ConcreteB __concrete_b_stub/*(...)*/; // -------------------------------------------------------------------------------------- /** Client **/ Abstract* p_abstract = Abstract::create(CONC_TYPE_A /* or CONC_TYPE_B */); // ... some code p_abstract->destroy(); // --------------------------------------------------------------------------------------
使用 Prototype 模式的好处 :
1. 对客户端隐藏具体的产品类 (product classes), 这样就能够减少客户端可见的名字数目,降低系统的复杂性;
2. 可以动态的添加或者删除产品类的原型;
3. 相对于工厂方法模式,简化了继承体系结构。
4. 可以动态配置一个应用所能使用的类。在上面代码中, 所有的原型是在 main 函数执行之前注册到 prototype manager 持有的注册表中的(静态初始化过程)。 实际上, 注册表项的加载可以推迟到 main 函数执行后, 即动态地加载到注册表中。