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模式:
在Base的实现文件中,我加入:
“嗯,不错,”我思索着。”向厂注册一个函数后,生成实例就如数1、2、3那么简单”
我继续生成一个派生类,以测试通过厂来生成实例。在派生类的实现中,我加入:
但编译器冷冷地阻住了我-它提示不能将CreateDerived转换为所需类型。在迷惑了好一阵之后,我想起以前经历过的隐式地转换为指向Base的 指针的问题 [2]。我认识到我又一次遇到编译器不能进行隐式指针转换问题,所以我稍稍修改了create函数:
回顾一下基类,我注意到注册代码几乎相同,所以我写了个替代的宏:
使用这个宏很简单:
“近一小时的工作做得不错,”我在完成时嘟囔着。
“是的,确实如此,我的孩子。但你还能做得更好。”
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如出现时一样已悄悄地不见了。我稍稍有些哆嗦,又转回去继续工作。
过了一会儿,我实现了一个厂模板:
我认为,不是所有的类都用std::string作为键值,所以我将键值类型作为一个模板参数。所有函数的实现都和我在BaseFactory中写过的一模一样,除了那个注册函数之外。我用一个更优雅的模板来实现它的:
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,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)
单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
<
这样在游戏时只要用SelectLevel()函数选择难度后. pFactory_就指向了实际的工厂.
以后需要Soldier等的时候只要用
就可以了.
要使用抽象工厂模式.本来是要自己手工写这些类的.像前边的:
这3个类就自动的被编译器弄好了. 它们用起来和前边手工写的一样.
只是你需要产生一个具体士兵时把原来的
改成
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模式:
- class BaseFactory
- {
- typedef std::auto_ptr<Base> (*BaseCreateFn)();
- typedef std::map<std::string, BaseCreateFn> FnRegistry;
- FnRegistry registry;
- BaseFactory() {}
- BaseFactory(const BaseFactory &); // Not implemented
- BaseFactory & operator=(const BaseFactory &); // Not implemented
- public:
- static BaseFactory & instance() { static BaseFactory bf; return bf; }
- bool RegCreateFn(const std::string &, BaseCreateFn);
- std::auto_ptr<Base> Create(const std::string &) const;
- };
- bool BaseFactory::RegCreateFn(const std::string & className, BaseCreateFn fn)
- {
- registry[className] = fn;
- return true;
- }
- std::auto_ptr<Base> BaseFactory::Create(const std::string &className) const
- {
- std::auto_ptr<Base> theObject(0);
- FnRegistry::const_iterator regEntry = registry.find(className);
- if (regEntry != registry.end())
- {
- theObject = regEntry->second();
- }
- return theObject;
- }
在Base的实现文件中,我加入:
- namespace
- {
- std::auto_ptr<Base> CreateBase()
- {
- return std::auto_ptr<Base>(new Base);
- }
- bool dummy = BaseFactory::instance().RegCreateFn(“Base”, CreateBase);
- }
“嗯,不错,”我思索着。”向厂注册一个函数后,生成实例就如数1、2、3那么简单”
- int main()
- {
- std::auto_ptr<Base> anObject = BaseFactory::instance().Create(“Base”);
- }
我继续生成一个派生类,以测试通过厂来生成实例。在派生类的实现中,我加入:
- namespace
- {
- std::auto_ptr<Derived> CreateDerived()
- {
- return std::auto_ptr<Derived>(new Derived);
- }
- bool dummy = BaseFactory::instance().RegCreateFn(“Derived”, CreateDerived);
- }
但编译器冷冷地阻住了我-它提示不能将CreateDerived转换为所需类型。在迷惑了好一阵之后,我想起以前经历过的隐式地转换为指向Base的 指针的问题 [2]。我认识到我又一次遇到编译器不能进行隐式指针转换问题,所以我稍稍修改了create函数:
- namespace
- {
- std::auto_ptr<Base> CreateDerived()
- {
- return std::auto_ptr<Base>(new Derived);
- }
- bool dummy = BaseFactory::instance().RegCreateFn(“Derived”, CreateDerived);
- }
回顾一下基类,我注意到注册代码几乎相同,所以我写了个替代的宏:
- #define REGISTER_CLASS(BASE_CLASS, DERIVED_CLASS) /
- namespace /
- { /
- std::auto_ptr<BASE_CLASS> Create##DERIVED_CLASS() /
- { /
- return std::auto_ptr<BASE_CLASS>(new DERIVED_CLASS); /
- } /
- bool dummy=BaseFactory::instance().RegCreateFn( /
- #DERIVED_CLASS, Create##DERIVED_CLASS); /
- }
使用这个宏很简单:
- REGISTER_CLASS(Base, Base)
“近一小时的工作做得不错,”我在完成时嘟囔着。
“是的,确实如此,我的孩子。但你还能做得更好。”
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如出现时一样已悄悄地不见了。我稍稍有些哆嗦,又转回去继续工作。
过了一会儿,我实现了一个厂模板:
- template <class ManufacturedType, typename ClassIDKey=std::string>
- class GenericFactory
- {
- typedef std::auto_ptr<ManufacturedType> (*BaseCreateFn)();
- typedef std::map<ClassIDKey, BaseCreateFn> FnRegistry;
- FnRegistry registry;
- GenericFactory();
- GenericFactory(const GenericFactory&); // Not implemented
- GenericFactory &operator=(const GenericFactory&); // Not implemented
- public:
- static GenericFactory &instance();
- void RegCreateFn(const ClassIDKey &, BaseCreateFn);
- std::auto_ptr<ManufacturedType> Create(const ClassIDKey &className) const;
- };
我认为,不是所有的类都用std::string作为键值,所以我将键值类型作为一个模板参数。所有函数的实现都和我在BaseFactory中写过的一模一样,除了那个注册函数之外。我用一个更优雅的模板来实现它的:
- template <class AncestorType, class ManufacturedType, typename ClassIDKey=std::string>
- class RegisterInFactory
- {
- public:
- static std::auto_ptr<AncestorType> CreateInstance()
- {
- return std::auto_ptr<AncestorType>(new ManufacturedType);
- }
- RegisterInFactory(const ClassIDKey &id)
- {
- GenericFactory<AncestorType>::instance().RegCreateFn(id, CreateInstance);
- }
- };
- 下边是从Loki的头文件Factory.h中复制的部分代码:
- namespace Loki
- {
- /// /class DefaultFactoryError
- ///
- /// /ingroup FactoryGroup
- /// Manages the "Unknown Type" error in an object factory
- template <typename IdentifierType, class AbstractProduct>
- struct DefaultFactoryError
- //向Factory请求创建一个未登记的id时.抛出异常Exception().
- {
- struct Exception : public std::exception
- {
- const char* what() const throw() { return "Unknown Type"; }
- };
- static AbstractProduct* OnUnknownType(IdentifierType)
- {
- throw Exception();
- }
- };
- template
- <
- class AbstractProduct,
- typename IdentifierType,
- typename ProductCreator = AbstractProduct* (*)(),
- template<typename, class>
- class FactoryErrorPolicy = DefaultFactoryError
- >
- class Factory
- : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
- {
- public:
- bool Register(const IdentifierType& id, ProductCreator creator)
- {
- return associations_.insert(
- typename IdToProductMap::value_type(id, creator)).second;
- }
- bool Unregister(const IdentifierType& id)
- {
- return associations_.erase(id) == 1;
- }
- AbstractProduct* CreateObject(const IdentifierType& id)
- {
- typename IdToProductMap::iterator i = associations_.find(id);
- if (i != associations_.end())
- {
- return (i->second)();
- }
- return this->OnUnknownType(id);
- }
- private:
- typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
- IdToProductMap associations_;
- };
- } // 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,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)
单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
<
- class Soldier; //抽象的士兵基类
- class SillySoldier : public Soldier; //简单士兵类
- class BadSoldier : public Soldier; //厉害士兵类
- class Monster; // 抽象的怪兽基类
- class SillyMonster : public Monster; //简单怪兽类
- class BadMonster : public Monster; //厉害的怪兽类
- class SuperMonster; //抽象的超级怪兽基类
- class SillySuperMonster : public SuperMonster; //简单的超级怪兽
- class BadSuperMonster : public SuperMonster; //厉害的超级怪兽
- //抽象工厂
- class AbstroctEnemyFactory {
- public:
- virtual Soldier* MakeSoldier() = 0;
- virtual Monster* MakeMonster() = 0;
- virtual SuperMonster* MakeSuperMonster() = 0;
- };
- //简单任务中使用的具体工厂. 产品是一系列愚蠢的敌人.
- class EasyLevelEnemyFactory : public AbstractEnemyFactory {
- Soldier* MakeSoldier() { return new SillySoldier; }
- Monster* MakeMonster() { return new SillyMonster; }
- SuperMonster* MakeSuperMonster() { return new SillySuperMonster; }
- };
- //困难任务中使用的具体工厂. 产品是一系列厉害敌人.
- class DieHardLevelEnemyFactory : public AbstractEnemyFactory {
- Soldier* MakeSoldier() { return new BadSoldier; }
- Monster* MakeMonster() { return new BadMonster; }
- SuperMonster* MakeSuperMonster() { return new BadSuperMonster; }
- };
- //游戏类
- class GameApp {
- public:
- ///............
- void SelectLevel() {
- if ( 用户选择简单模式 )
- pFactory_ = new EasyLevelEnemyFactory;
- else
- pFactory_ = new DieHardLevelEnemyFactory;
- }
- private:
- AbstractEnemyFactory* pFactory_;
- };
这样在游戏时只要用SelectLevel()函数选择难度后. pFactory_就指向了实际的工厂.
以后需要Soldier等的时候只要用
- pFactory->MakeSoldier() ;
就可以了.
要使用抽象工厂模式.本来是要自己手工写这些类的.像前边的:
- //抽象工厂
- class AbstroctEnemyFactory {
- public:
- virtual Soldier* MakeSoldier() = 0;
- virtual Monster* MakeMonster() = 0;
- virtual SuperMonster* MakeSuperMonster() = 0;
- };
- //简单任务中使用的具体工厂. 产品是一系列愚蠢的敌人.
- class EasyLevelEnemyFactory : public AbstractEnemyFactory {
- Soldier* MakeSoldier() { return new SillySoldier; }
- Monster* MakeMonster() { return new SillyMonster; }
- SuperMonster* MakeSuperMonster() { return new SillySuperMonster; }
- };
- //困难任务中使用的具体工厂. 产品是一系列厉害敌人.
- class DieHardLevelEnemyFactory : public AbstractEnemyFactory {
- Soldier* MakeSoldier() { return new BadSoldier; }
- Monster* MakeMonster() { return new BadMonster; }
- SuperMonster* MakeSuperMonster() { return new BadSuperMonster; }
- };
- 但是书上发明了两个现代化的类模板 AbstractFactory 和 ConcreteFactory
- 它们会自动化的帮你生成你想要的抽象工厂和具体工厂类. 例如:
- //抽象工厂
- typedef AbstractFactory< LOKI_TYPELIST_3(Soldier, Monster, SuperMonster)>
- AbstractEnemyFactory;
- //两个具体工厂(简单敌人工厂和困难敌人工厂)
- typedef ConcreteFactory<AbstractEnemyFactory, OpNewFactoryUnit,
- LOKI_TYPELIST_3(SillySoldier, SillyMonster, SillySuperMonster)>
- EasyLevelEnemyFactory;
- typedef ConcreteFactory<AbstractEnemyFactory, OpNewFactoryUnit,
- LOKI_TYPELIST_3(BadSoldier, BadMonster, BadSuperMonster)>
- DieHardLevelEnemyFactory;
这3个类就自动的被编译器弄好了. 它们用起来和前边手工写的一样.
只是你需要产生一个具体士兵时把原来的
- pFactory->MakeSoldier() ;
改成
- pFactory->Create<Monster>() ;