5种创建型模式的权衡的讨论

1。abstract   factory    
2。builder    
3。factory   method    
4。prototype    
5。sigleton  


贴上copy过来的文章,大家认为下面真的是抽象工厂吗?  
 -------------------------------------  
 Abstract   Factory,   Template   Style    
 taodm翻译  
   
 --------------------------------------------------------------------------------  
   
 “我们知道这是什么吗?”我指着放在前面金属台上的设备。这是在冰原下勘探到的第一批物体之一。    
   
 珍妮摇着头。”没呢,伙计。它可能是个奖杯,飞船推进器,儿童玩具,或就只是垃圾。上周,我们曾认为将能源系统制造出来了,供这个和其它一些设备用的,但在加入燃料后什么也没发生。随着能源的远去,技术又重回到了画图板上,但他们认为很快能搞定它。.”    
   
 “凭什么?”    
   
 “希望。”    
   
 我瞄了一下墙上的钟。”好吧,时间差不多了。我在发抖,我很冷。每次我们要求勘探队给我们些新的东西来鼓捣时,他们总弄出些新的不同的东西。我真希望能弄明白哪怕其中任何一个。”    
   
 “我希望我们对从这个‘artifact   factory’中出产的东西能知道得更多些。”珍妮同意。    
   
 “这使我回想起以前发生在我身上的一些事,在那时……”    
   
 珍妮眨着她的眼睛。”告诉为,什么时候我们可以到个暖和的地方。”    
   
   
 --------------------------------------------------------------------------------  
   
 “坏消息,”我越过隔板向温迪嚷道。    
   
 “呒?”她探起头。    
   
 “你知道我上周写的类的吧。”    
   
 “不是十分清楚,说下去。”    
   
 我没在意。”好吧,”我继续着,”我必须为它实现一个类厂。Guru建议我看一下客户群写的类厂。”    
   
 “嗯,于是?”突然沮丧显现在她脸上:”噢。鲍勃写的,是吧?”    
   
 我沉重地点点头。”是的,我唯一能给予他的称赞是   —每当我打开他的代码,我都能学会有些事不该如何实现。”温迪哈哈地笑着坐回位置上。    
   
 我叹了口气,然后check   out源码。还好,没我想象的那么坏。只不过是极大量的if语句嵌套-我做好了坏得多的准备的。但已是够可怕的代码了,所以根据Guru的忠告,我准备实 现一个Abstract   Class   Factory   [1]。由于没有多线程和并发的需求我决定将厂实现为singleton模式:    
   
  1. class   BaseFactory     
  2. {     
  3.         typedef   std::auto_ptr<Base>   (*BaseCreateFn)();     
  4.         typedef   std::map<std::string,   BaseCreateFn>   FnRegistry;     
  5.         FnRegistry   registry;     
  6.         BaseFactory()   {}     
  7.         BaseFactory(const   BaseFactory   &);   //   Not   implemented     
  8.         BaseFactory   &   operator=(const   BaseFactory   &);   //   Not   implemented     
  9. public:     
  10.         static   BaseFactory   &   instance()   {   static   BaseFactory   bf;   return   bf;   }     
  11.         bool   RegCreateFn(const   std::string   &,   BaseCreateFn);     
  12.         std::auto_ptr<Base>   Create(const   std::string   &)   const;     
  13. };     
  14. bool   BaseFactory::RegCreateFn(const   std::string   &   className,   BaseCreateFn   fn)     
  15. {     
  16.         registry[className]   =   fn;     
  17.         return   true;     
  18. }     
  19. std::auto_ptr<Base>   BaseFactory::Create(const   std::string   &className)   const     
  20. {     
  21.         std::auto_ptr<Base>   theObject(0);     
  22.         FnRegistry::const_iterator   regEntry   =   registry.find(className);     
  23.         if   (regEntry   !=   registry.end())       
  24.         {     
  25.                 theObject   =   regEntry->second();     
  26.         }     
  27.         return   theObject;     
  28. }     
  29.     

 在Base的实现文件中,我加入:    
   
  1. namespace       
  2. {     
  3.         std::auto_ptr<Base>   CreateBase()     
  4.         {     
  5.                 return   std::auto_ptr<Base>(new   Base);     
  6.         }     
  7.         bool   dummy   =   BaseFactory::instance().RegCreateFn(“Base”,   CreateBase);     
  8. }     

   
 “嗯,不错,”我思索着。”向厂注册一个函数后,生成实例就如数1、2、3那么简单”    
   
  1. int   main()     
  2. {     
  3.         std::auto_ptr<Base>   anObject   =   BaseFactory::instance().Create(“Base”);     
  4. }     
  5.     

 我继续生成一个派生类,以测试通过厂来生成实例。在派生类的实现中,我加入:    
   
  1. namespace       
  2. {     
  3.         std::auto_ptr<Derived>   CreateDerived()     
  4.         {     
  5.                 return   std::auto_ptr<Derived>(new   Derived);     
  6.         }     
  7.         bool   dummy   =   BaseFactory::instance().RegCreateFn(“Derived”,   CreateDerived);     
  8. }     
  9.     

 但编译器冷冷地阻住了我-它提示不能将CreateDerived转换为所需类型。在迷惑了好一阵之后,我想起以前经历过的隐式地转换为指向Base的 指针的问题   [2]。我认识到我又一次遇到编译器不能进行隐式指针转换问题,所以我稍稍修改了create函数:    
   
  1. namespace       
  2. {     
  3.         std::auto_ptr<Base>   CreateDerived()     
  4.         {     
  5.                 return   std::auto_ptr<Base>(new   Derived);     
  6.         }     
  7.         bool   dummy   =   BaseFactory::instance().RegCreateFn(“Derived”,   CreateDerived);     
  8. }     

   
 回顾一下基类,我注意到注册代码几乎相同,所以我写了个替代的宏:    
   
  1. #define   REGISTER_CLASS(BASE_CLASS,   DERIVED_CLASS)   /     
  2. namespace   /     
  3. {   /     
  4.         std::auto_ptr<BASE_CLASS>   Create##DERIVED_CLASS()   /     
  5.         {   /     
  6.                 return   std::auto_ptr<BASE_CLASS>(new   DERIVED_CLASS);   /     
  7.         }   /     
  8.         bool   dummy=BaseFactory::instance().RegCreateFn(   /     
  9.                 #DERIVED_CLASS,   Create##DERIVED_CLASS);   /     
  10. }     
  11.     

 使用这个宏很简单:    
   
  1. REGISTER_CLASS(Base,   Base)     
  2.     

 “近一小时的工作做得不错,”我在完成时嘟囔着。    
   
 “是的,确实如此,我的孩子。但你还能做得更好。”    
   
 Guru轻柔的声音出现在身后时,我还是会被吓一跳。”什么-?”    
   
 “这样展开的宏,”她解释道,”是难以阅读和理解的,并且宏不是类型安全的。还有,这个bool变量是什么目的?”    
   
 “这个嘛,”我有些抵触地答道,”它是我唯一能想到的,能确保注册函数被自动调用的方法。我不想在每增加一个新类时都要修改典型厂的代码。”    
   
 她点点头。”很聪明的想法,我的孩子。但是,你的厂不足够通用。会有越来越多的需要abstract   factory的类。我期望你创建这样一个厂:能在它被应用的每个类层次上自动处理,而不是要求修改(create   a   factory   that   will   handle,   not   require,   modification   for   each   class   hierarchy   it   will   be   used   on)。”    
   
 “一个通用的abstract   factory?这有些苛求,不是吗?”    
   
 “徒弟,你从不畏惧挑战,是吧?‘Experience   is   by   industry   achieved...   “    
   
 “‘...   and   perfected   by   the   swift   course   of   time’,”我接道[3]。   “我从不畏惧挑战,但我不能将进度表置之不理地花费大量时间。”    
   
 “你已经几乎就做到了。你所需要的就是考虑通用,”她指点道。    
   
 “考虑通用……也就是说,模板!”我嚷着转向显示器。几分钟之后,我向身后瞄了一下,Guru如出现时一样已悄悄地不见了。我稍稍有些哆嗦,又转回去继续工作。    
   
 过了一会儿,我实现了一个厂模板:    
   
  1. template   <class   ManufacturedType,   typename   ClassIDKey=std::string>     
  2. class   GenericFactory     
  3. {     
  4.         typedef   std::auto_ptr<ManufacturedType>   (*BaseCreateFn)();     
  5.         typedef   std::map<ClassIDKey,   BaseCreateFn>   FnRegistry;     
  6.         FnRegistry   registry;     
  7.         GenericFactory();     
  8.         GenericFactory(const   GenericFactory&);   //   Not   implemented     
  9.         GenericFactory   &operator=(const   GenericFactory&);   //   Not   implemented     
  10. public:     
  11.         static   GenericFactory   &instance();     
  12.         void   RegCreateFn(const   ClassIDKey   &,   BaseCreateFn);     
  13.         std::auto_ptr<ManufacturedType>   Create(const   ClassIDKey   &className)   const;     
  14. };     
  15.     

 我认为,不是所有的类都用std::string作为键值,所以我将键值类型作为一个模板参数。所有函数的实现都和我在BaseFactory中写过的一模一样,除了那个注册函数之外。我用一个更优雅的模板来实现它的:    
   
  1. template   <class   AncestorType,   class   ManufacturedType,   typename   ClassIDKey=std::string>     
  2. class   RegisterInFactory     
  3. {     
  4. public:     
  5.         static   std::auto_ptr<AncestorType>   CreateInstance()     
  6.         {     
  7.                 return   std::auto_ptr<AncestorType>(new   ManufacturedType);     
  8.         }     
  9.         RegisterInFactory(const   ClassIDKey   &id)     
  10.         {     
  11.                 GenericFactory<AncestorType>::instance().RegCreateFn(id,   CreateInstance);     
  12.         }     
  13. };     


  1. 下边是从Loki的头文件Factory.h中复制的部分代码:     
  2.       
  3.       
  4.       
  5.   namespace   Loki     
  6.   {     
  7.       
  8.        
  9.   ///     /class   DefaultFactoryError     
  10.   ///     
  11.   ///     /ingroup   FactoryGroup     
  12.   ///     Manages   the   "Unknown   Type"   error   in   an   object   factory     
  13.        
  14.       
  15.           template   <typename   IdentifierType,   class   AbstractProduct>     
  16.           struct   DefaultFactoryError     
  17.           //向Factory请求创建一个未登记的id时.抛出异常Exception().     
  18.           {     
  19.                   struct   Exception   :   public   std::exception     
  20.                   {     
  21.                           const   char*   what()   const   throw()   {   return   "Unknown   Type";   }     
  22.                   };     
  23.                       
  24.                   static   AbstractProduct*   OnUnknownType(IdentifierType)     
  25.                   {     
  26.                           throw   Exception();     
  27.                   }     
  28.           };     
  29.               
  30.               
  31.           template     
  32.           <     
  33.                   class   AbstractProduct,       
  34.                   typename   IdentifierType,     
  35.                   typename   ProductCreator   =   AbstractProduct*   (*)(),     
  36.                   template<typename,   class>     
  37.                           class   FactoryErrorPolicy   =   DefaultFactoryError     
  38.           >     
  39.           class   Factory       
  40.                   :   public   FactoryErrorPolicy<IdentifierType,   AbstractProduct>     
  41.           {     
  42.           public:     
  43.                   bool   Register(const   IdentifierType&   id,   ProductCreator   creator)     
  44.                   {     
  45.                           return   associations_.insert(     
  46.                                   typename   IdToProductMap::value_type(id,   creator)).second;     
  47.                   }     
  48.                       
  49.                   bool   Unregister(const   IdentifierType&   id)     
  50.                   {     
  51.                           return   associations_.erase(id)   ==   1;     
  52.                   }     
  53.                       
  54.                   AbstractProduct*   CreateObject(const   IdentifierType&   id)     
  55.                   {     
  56.                           typename   IdToProductMap::iterator   i   =   associations_.find(id);     
  57.                           if   (i   !=   associations_.end())     
  58.                           {     
  59.                                   return   (i->second)();     
  60.                           }     
  61.                           return   this->OnUnknownType(id);     
  62.                   }     
  63.                       
  64.           private:     
  65.                   typedef   AssocVector<IdentifierType,   ProductCreator>   IdToProductMap;     
  66.                   IdToProductMap   associations_;     
  67.           };     
  68.       
  69.       
  70.   }   //   namespace   Loki  


引用

1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory    
     
   工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。    
     
   2、BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面 每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞掂,这就是我的“我爱你” builder。(这一定比美军在伊拉克用的翻译机好卖)    
     
   建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。    
     
   3、FACTORY   METHOD   —   请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory   Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。    
     
   工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。    
     
   4、PROTOTYPE—跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。(100块钱一份,你要不要)    
     
   原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增 加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。    
     
   5、SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)    
     
   单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。


<
  1.     
  2. class   Soldier;     //抽象的士兵基类       
  3. class   SillySoldier   :   public   Soldier;   //简单士兵类       
  4. class   BadSoldier   :   public   Soldier;   //厉害士兵类     
  5.     
  6. class   Monster;   //   抽象的怪兽基类     
  7. class   SillyMonster   :   public   Monster;   //简单怪兽类       
  8. class   BadMonster   :   public   Monster;   //厉害的怪兽类     
  9.     
  10. class   SuperMonster;   //抽象的超级怪兽基类       
  11. class   SillySuperMonster   :   public   SuperMonster;     //简单的超级怪兽     
  12. class   BadSuperMonster   :   public   SuperMonster;         //厉害的超级怪兽     
  13.     
  14. //抽象工厂     
  15. class   AbstroctEnemyFactory   {       
  16. public:     
  17.         virtual   Soldier*   MakeSoldier()   =   0;     
  18.         virtual   Monster*   MakeMonster()   =   0;     
  19.         virtual   SuperMonster*   MakeSuperMonster()   =   0;     
  20. };     
  21.     
  22. //简单任务中使用的具体工厂.   产品是一系列愚蠢的敌人.     
  23. class   EasyLevelEnemyFactory   :   public   AbstractEnemyFactory   {     
  24.         Soldier*   MakeSoldier()   {   return   new   SillySoldier;   }     
  25.         Monster*   MakeMonster()   {   return   new   SillyMonster;   }     
  26.         SuperMonster*   MakeSuperMonster()   {   return   new   SillySuperMonster;   }     
  27. };     
  28.     
  29. //困难任务中使用的具体工厂.   产品是一系列厉害敌人.     
  30. class   DieHardLevelEnemyFactory   :   public   AbstractEnemyFactory   {     
  31.         Soldier*   MakeSoldier()   {   return   new   BadSoldier;   }     
  32.         Monster*   MakeMonster()   {   return   new   BadMonster;   }     
  33.         SuperMonster*   MakeSuperMonster()   {   return   new   BadSuperMonster;   }     
  34. };     
  35.     
  36. //游戏类     
  37. class   GameApp   {     
  38. public:     
  39.         ///............     
  40.         void   SelectLevel()   {     
  41.                 if   (   用户选择简单模式   )       
  42.                         pFactory_   =   new   EasyLevelEnemyFactory;     
  43.                 else       
  44.                         pFactory_   =   new   DieHardLevelEnemyFactory;     
  45.         }     
  46. private:     
  47.         AbstractEnemyFactory*   pFactory_;     
  48. };     
  49.     

 这样在游戏时只要用SelectLevel()函数选择难度后.   pFactory_就指向了实际的工厂.  
 以后需要Soldier等的时候只要用  
  1. pFactory->MakeSoldier() ;  

就可以了.

要使用抽象工厂模式.本来是要自己手工写这些类的.像前边的:  
   
  1. //抽象工厂     
  2. class   AbstroctEnemyFactory   {       
  3. public:     
  4.         virtual   Soldier*   MakeSoldier()   =   0;     
  5.         virtual   Monster*   MakeMonster()   =   0;     
  6.         virtual   SuperMonster*   MakeSuperMonster()   =   0;     
  7. };     
  8.     
  9. //简单任务中使用的具体工厂.   产品是一系列愚蠢的敌人.     
  10. class   EasyLevelEnemyFactory   :   public   AbstractEnemyFactory   {     
  11.         Soldier*   MakeSoldier()   {   return   new   SillySoldier;   }     
  12.         Monster*   MakeMonster()   {   return   new   SillyMonster;   }     
  13.         SuperMonster*   MakeSuperMonster()   {   return   new   SillySuperMonster;   }     
  14. };     
  15.     
  16. //困难任务中使用的具体工厂.   产品是一系列厉害敌人.     
  17. class   DieHardLevelEnemyFactory   :   public   AbstractEnemyFactory   {     
  18.         Soldier*   MakeSoldier()   {   return   new   BadSoldier;   }     
  19.         Monster*   MakeMonster()   {   return   new   BadMonster;   }     
  20.         SuperMonster*   MakeSuperMonster()   {   return   new   BadSuperMonster;   }     
  21. };     
  22.     
  23.     
  24. 但是书上发明了两个现代化的类模板   AbstractFactory   和   ConcreteFactory       
  25. 它们会自动化的帮你生成你想要的抽象工厂和具体工厂类.   例如:     
  26.     
  27. //抽象工厂     
  28. typedef   AbstractFactory<   LOKI_TYPELIST_3(Soldier,   Monster,   SuperMonster)>       
  29.                     AbstractEnemyFactory;       
  30.     
  31. //两个具体工厂(简单敌人工厂和困难敌人工厂)     
  32. typedef   ConcreteFactory<AbstractEnemyFactory,   OpNewFactoryUnit,       
  33.                 LOKI_TYPELIST_3(SillySoldier,   SillyMonster,   SillySuperMonster)>       
  34.                 EasyLevelEnemyFactory;     
  35. typedef   ConcreteFactory<AbstractEnemyFactory,   OpNewFactoryUnit,       
  36.                 LOKI_TYPELIST_3(BadSoldier,   BadMonster,   BadSuperMonster)>       
  37.                 DieHardLevelEnemyFactory;     

   
 这3个类就自动的被编译器弄好了.   它们用起来和前边手工写的一样.    
 只是你需要产生一个具体士兵时把原来的  
  1. pFactory->MakeSoldier() ;  
   
 改成  
  1. pFactory->Create<Monster>()  ;     
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下 4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值