原型模式
原型模式,如其名称,核心就是要实现一个原型类,该类支持clone操作,从而客户可以从原型克隆出具体的类。其效果主要有如下:
可以动态增加和删除产品。这个就是通过clone代替new等操作,也避免了客户与具体类打交道。
通过改变对象的值,指定新的对象。clone出一个新对象后可以修改其参数改变对象,如果参数较多,可以提供类似initialize方法。
减少creator类,减少子类数目。客户看起来直接从一个原型克隆出一个新的对象,而不是跟工厂方法打交道,因而少了一个类层次。
动态配置应用,这个真是没想明白。也没个例子,我想大致意思就是将原型编译成动态库等,初始化阶段构造原型对象,运行时从原型克隆出新的类吧。
写了个简单demo,供参考:
/** * @file test_prototype.cpp * @author itegel * @date 2013/09/18 15:15:26 * @brief * **/ #include <iostream> #include <string> #include <map> using namespace std; class Prototype{ public: Prototype(){_myself = "Prototype";} ~Prototype(){} void ShowMyself(){ cout<<"I am "<<_myself<<endl; } void SetMyself(string str){ _myself = str; } virtual Prototype * Clone() = 0; private: string _myself; }; //Colour prototype for all colours class Colour:public Prototype{ public: Colour(){ SetRGB(0,0,0); SetMyself("Colour"); } ~Colour(){} void SetRGB(int r, int g, int b){ _R = r; _G = g; _B = b; } int GetR() const {return _R;} int GetG() const {return _G;} int GetB() const {return _B;} void Print(){ cout<<"R:G:B=>"<<_R<<":"<<_G<<":"<<_B<<endl; } Colour(const Colour& other){ this->SetRGB(other.GetR(),other.GetG(), other.GetB()); } virtual Colour * Clone(){ return new Colour(*this); } private: int _R; int _G; int _B; }; //Type prototype for all colours class Type:public Prototype{ public: Type(){ SetTypeStr("0,0;"); SetMyself("Type"); } ~Type(){} void SetTypeStr(string type){ _type_str = type; } string GetTypeStr() const{return _type_str;} void Print(){ cout<<"type:"<<_type_str<<endl; } Type(const Type& other){ this->SetTypeStr(other.GetTypeStr()); } virtual Type * Clone(){ return new Type(*this); } private: string _type_str; }; class PrototypeMapManager{ public: PrototypeMapManager(){} ~PrototypeMapManager(){} int RegisterPrototype(string name, Prototype * prototype){ map<string, Prototype *>::iterator iter = _prototype_map.find(name); if (iter != _prototype_map.end()){ cout<<"prototype["<<name<<"] already exist!"<<endl; return -1; } _prototype_map.insert(pair<string, Prototype *>(name, prototype)); return 0; } Prototype * GetPrototype(string name){ map<string, Prototype *>::iterator iter = _prototype_map.find(name); if (iter == _prototype_map.end()){ cout<<"prototype["<<name<<"] not find!"<<endl; return NULL; } else { return iter->second; } } private: map<string, Prototype *> _prototype_map; }; //client int main(){ //test 易做图 prototype Colour * prototype = new Colour(); cout<<"1. prototype:"<<endl; prototype->Print(); Colour * blue = prototype->Clone(); cout<<"2. after cloned:"<<endl; blue->Print(); blue->SetRGB(0,0,255); cout<<"3. after set property:"<<endl; blue->Print(); delete prototype; Type * type_prototype = new Type(); Type * line = type_prototype->Clone(); line->SetTypeStr("0,0;99,99;"); cout<<"4. line:"<<endl; line->Print(); //test dynamic produce objects cout<<endl; cout<<"DYNAMIC produce TEST"<<endl; PrototypeMapManager ProtoMgr; Colour * colour_prototype = new Colour(); ProtoMgr.RegisterPrototype("Colour", colour_prototype); blue->SetMyself("Blue"); ProtoMgr.RegisterPrototype("Blue", blue); ProtoMgr.RegisterPrototype("Type", type_prototype); line->SetMyself("Line"); ProtoMgr.RegisterPrototype("Line", line); Prototype * clr_proto = ProtoMgr.GetPrototype("Colour"); clr_proto->ShowMyself(); Prototype * blue_proto = ProtoMgr.GetPrototype("Blue"); blue_proto->ShowMyself(); Prototype * red_proto = blue_proto->Clone(); red_proto->SetMyself("Red"); red_proto->ShowMyself(); Prototype * line_proto = ProtoMgr.GetPrototype("Line"); line_proto->ShowMyself(); return 0; }
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
执行结果如下:
1. prototype: R:G:B=>0:0:0 2. after cloned: R:G:B=>0:0:0 3. after set property: R:G:B=>0:0:255 4. line: type:0,0;99,99; DYNAMIC produce TEST I am Colour I am Blue I am Red I am Line
prototype比较麻烦的一点就是clone操作的定义有时候不是那么容易的。涉及到深浅拷贝等问题。具体网上有很多讨论,这里就不抄袭了。对于简单类这个其实也不是什么困难事。
补充:软件开发 , C++ ,