您的位置:首页 > 其它

[学习笔记]设计模式之Facade

2014-03-13 16:55 260 查看

写在前面

为方便读者,本文已添加至索引

设计模式

学习笔记索引

Facade(外观)模式定义了一个高层接口,它能为子系统中的一组接口提供一个一致的界面,从而使得这一子系统更加容易使用。欢迎回到时の魔导士的魔法世界。在对战坏女巫的魔法生物一役中(见Bridge模式笔记),白雪公主获得大逆转胜利机会的关键是附魔武器的诞生。但是,普通的武器工坊(见FactoryMethod模式笔记)生产不了附魔武器,只能是通过特殊的附魔工坊获得。经过这一战之后,大家也觉得除了武器,还需要能保护身体的护甲来抵挡伤害。因此,霍比特人们又打算建立一些护甲工坊。如此一来,用于生产战斗用品的系统就越来越多了。小霍比特人们如果需要获得一整套适合自己的战斗用品,就不得不分别调用每个系统的生产方法。事实上,小霍比特人们并不关心每个系统具体的工作细节,他们只想要得到一件成品而已。对于他们而言,这些生产系统中那些功能强大但层次较低的接口只会使他们的任务复杂化。

为了让小霍比特人们的生活、战斗更便利,好女巫格琳达(Glinda原型请参见《魔境仙踪》,当然,你不会忘记一点:我肯定不会忠于原著)为他们提供了一个高层接口,并且对他们屏蔽了这些生产系统类——格琳达的小屋,在森林里面正式开业了。于是小霍比特人们只需要来到小屋中,告诉Glinda自己需要什么,再付上一点点小酬劳,就可以得到想到的东西啦。

class ArmorFactory : public VisualObject {
public:
virtual Armor* createArmor() = 0;
}


ArmorFactory
好啦,该去参观参观格琳达的小屋HouseOfGlinda了:

#define NOTHING    0

class HouseOfGlinda {
public:
VisualObject* onSale(int, int);   // a simple interface.

// ... It's a Singleton ...
static HouseOfGlinda* getInstance() {
if (_instance == 0) {
_instance = new HouseOfGlinda();
}

return _instance;
}

protected:
Weapon* getWeapon(int);
Weapon* getEnchantedWeapon(int, int);
  // ... Armor will be comming soon ...
private:
HouseOfGlinda();
static HouseOfGlinda* _instance;
}

VisualObject* HouseOfGlinda::onSale(int type, int info) {
if (WEAPON_SWORD == type ||
WEAPON_SHIELD == type ||
WEAPON_BOW == type
// ... other weapon ...
  ) {

if (NOTHING == info) {
return getWeapon(type);
}
else {
return getEnchantedWeapon(type, info);
}
}
// else for armor ...
}

Weapon* HouseOfGlinda::getWeapon(int type) {
WeaponFacotry* factory = 0;
Weapon* weapon = 0;
switch(type) {
case WEAPON_SWORD:
factory = new HonorOfFighter();
break;
case WEAPON_SHIELD:
factory = new BliefOfDefender();
break;
// ... other cases ...
default:
break;
}
weapon = factory->createWeapon();
if (factory) delete factory;
return weapon;
}

Weapon* HouseOfGlinda::getEnchantedWeapon(int type, int info) {
EnchantedWeaponFactory factory;
return factory.createEnchantedWeapon(info, type);
}


注意到HouseOfGlinda类中,onSale接口对客户屏蔽了子系统中的组件(譬如说WeaponFactory以及EnchantedWeaponFactory,甚至还在建设当中的ArmorFactory),作为客户的小霍比特人们只需要发送请求给HouseOfGlinda对象,它就能将消息转发给相应的子系统去处理,比方说,有人想要一把普通的剑,而另一个人想要一面冒着火焰的盾牌:

VisualObject* obj1 = HouseOfGlinda::getInstance->onSale(WEAPON_SHIELD, ENCHANTED_FIRE);
VisualObject* obj2 = HouseOfGlinda::getInstance->onSale(WEAPON_SWORD, NOTHING);


瞧,多方便呀。此外,如果真有需要,小霍比特人还是可以直接访问工坊从而获得私人定制的武器。当然通过格琳达的小屋会更加方便,这样他们有更多时间去享受啤酒和美食的乐趣了。

一张简单的UML图:



特点总结

Facade模式简单且易于理解,对于我们来说也很常用。它的优点如下:

它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。

它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。Facade模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。Facade模式可以消除复杂的循环依赖关系。这一点在客户程序与子系统是分别实现的时候尤为重要。

如果应用需要,它并不限制它们使用子系统类。因此我们可以在系统易用性和通用性之间加以选择。

写在最后

今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: