为方便读者,本文已添加至索引:html
Facade(外观)模式定义了一个高层接口,它能为子系统中的一组接口提供一个一致的界面,从而使得这一子系统更加容易使用。欢迎回到时の魔导士的魔法世界。在对战坏女巫的魔法生物一役中(见Bridge模式笔记),白雪公主得到大逆转胜利机会的关键是附魔武器的诞生。可是,普通的武器工坊(见FactoryMethod模式笔记)生产不了附魔武器,只能是经过特殊的附魔工坊得到。通过这一战以后,你们也以为除了武器,还须要能保护身体的护甲来抵挡伤害。所以,霍比特人们又打算创建一些护甲工坊。如此一来,用于生产战斗用品的系统就愈来愈多了。小霍比特人们若是须要得到一整套适合本身的战斗用品,就不得不分别调用每一个系统的生产方法。事实上,小霍比特人们并不关心每一个系统具体的工做细节,他们只想要获得一件成品而已。对于他们而言,这些生产系统中那些功能强大但层次较低的接口只会使他们的任务复杂化。设计模式
为了让小霍比特人们的生活、战斗更便利,好女巫格琳达(Glinda原型请参见《魔境仙踪》,固然,你不会忘记一点:我确定不会忠于原著)为他们提供了一个高层接口,而且对他们屏蔽了这些生产系统类——格琳达的小屋,在森林里面正式开业了。因而小霍比特人们只须要来到小屋中,告诉Glinda本身须要什么,再付上一点点小酬劳,就能够获得想到的东西啦。架构
那这一切跟咱们今天笔记的主题有什么关系呢?其实这正是Facade模式一个例子,咱们将在示例分析部分更加详细地探讨这个问题。首先仍是让咱们快速地熟悉下什么是Facade模式吧!ide
在咱们前来参观格琳达的小屋以前,不妨先回顾一下那些生产战斗用品的子系统,从而能更好地理解Facade模式工做的机制。因为在Bridge模式笔记中提到Weapon类的设计架构发生了改变,所以包括普通的武器工坊在内的设计也相应地进行了调整。学习
首先是咱们基本的Weapon类:spa
1 class Weapon : public VisualObject { 2 public: 3 Weapon(int); 4 ~Weapon() { delete _impl; } 5 // ... other ... 6 protected: 7 WeaponImpl* getWeaponImpl(); 8 private: 9 WeaponImpl* _impl; 10 } 11 12 Weapon::Weapon(int type) { 13 switch(type) 14 { 15 case WEAPON_SWORD: 16 _impl = new SwordImpl(); 17 break; 18 case WEAPON_SHIELD: 19 _impl = new ShieldImpl(); 20 break; 21 case WEAPON_BOW: 22 _impl = new BowImpl(); 23 break; 24 // ... other cases ... 25 default: 26 break; 27 } 28 }
还有调整后的WeaponFactory类以及它的子类们:设计
1 class WeaponFactory { 2 public: 3 virtual Weapon* createWeapon() = 0; 4 } 5 6 class HonorOfFighter : public WeaponFactory { 7 public: 8 HonorOfFighter(); 9 Weapon* createWeapon() { return new Weapon(WEAPON_SWORD); } 10 } 11 12 class BliefOfDefender : public WeaponFactory { 13 public: 14 BliefOfDefender(); 15 Weapon* createWeapon() { return new Weapon(WEAPON_SHEILD); } 16 } 17 18 class PrecisionOfHunter : public WeaponFactory { 19 public: 20 PrecisionOfHunter(); 21 Weapon* createWeapon() { return new Weapon(WEAPON_BOW); } 22 } 23 24 // ... other weapon factories ...
以及前文中提到的附魔工坊:代理
1 #define ENCHANTED_ICE 1 2 #define ENCHANTED_FIRE 2 3 #define ENCHANTED_SHOCK 3 4 5 class EnchantedWeaponFactory { 6 public: 7 Weapon* createEnchantedWeapon(int, int); 8 // ... other ... 9 } 10 11 EnchantedWeaponFactory::createEnchantedWeapon(int element, int type) { 12 return new EnchantedWeapon(element, type); 13 }
暂时尚未建成的护甲工坊:code
1 class ArmorFactory : public VisualObject { 2 public: 3 virtual Armor* createArmor() = 0; 4 }
好啦,该去参观参观格琳达的小屋HouseOfGlinda了:htm
1 #define NOTHING 0 2 3 class HouseOfGlinda { 4 public: 5 VisualObject* onSale(int, int); // a simple interface. 6 7 // ... It's a Singleton ... 8 static HouseOfGlinda* getInstance() { 9 if (_instance == 0) { 10 _instance = new HouseOfGlinda(); 11 } 12 13 return _instance; 14 } 15 16 protected: 17 Weapon* getWeapon(int); 18 Weapon* getEnchantedWeapon(int, int); 19 // ... Armor will be comming soon ... 20 private: 21 HouseOfGlinda(); 22 static HouseOfGlinda* _instance; 23 } 24 25 VisualObject* HouseOfGlinda::onSale(int type, int info) { 26 if (WEAPON_SWORD == type || 27 WEAPON_SHIELD == type || 28 WEAPON_BOW == type 29 // ... other weapon ... 30 ) { 31 32 if (NOTHING == info) { 33 return getWeapon(type); 34 } 35 else { 36 return getEnchantedWeapon(type, info); 37 } 38 } 39 // else for armor ... 40 } 41 42 Weapon* HouseOfGlinda::getWeapon(int type) { 43 WeaponFacotry* factory = 0; 44 Weapon* weapon = 0; 45 switch(type) { 46 case WEAPON_SWORD: 47 factory = new HonorOfFighter(); 48 break; 49 case WEAPON_SHIELD: 50 factory = new BliefOfDefender(); 51 break; 52 // ... other cases ... 53 default: 54 break; 55 } 56 weapon = factory->createWeapon(); 57 if (factory) delete factory; 58 return weapon; 59 } 60 61 Weapon* HouseOfGlinda::getEnchantedWeapon(int type, int info) { 62 EnchantedWeaponFactory factory; 63 return factory.createEnchantedWeapon(info, type); 64 }
注意到HouseOfGlinda类中,onSale接口对客户屏蔽了子系统中的组件(譬如说WeaponFactory以及EnchantedWeaponFactory,甚至还在建设当中的ArmorFactory),做为客户的小霍比特人们只须要发送请求给HouseOfGlinda对象,它就能将消息转发给相应的子系统去处理,比方说,有人想要一把普通的剑,而另外一我的想要一面冒着火焰的盾牌:
1 VisualObject* obj1 = HouseOfGlinda::getInstance->onSale(WEAPON_SHIELD, ENCHANTED_FIRE); 2 VisualObject* obj2 = HouseOfGlinda::getInstance->onSale(WEAPON_SWORD, NOTHING);
瞧,多方便呀。此外,若是真有须要,小霍比特人仍是能够直接访问工坊从而得到私人定制的武器。固然经过格琳达的小屋会更加方便,这样他们有更多时间去享受啤酒和美食的乐趣了。
一张简单的UML图:
Facade模式简单且易于理解,对于咱们来讲也很经常使用。它的优势以下:
今天的笔记就到这里了,欢迎你们批评指正!若是以为能够的话,好文推荐一下,我会很是感谢的!