为方便读者,本文已添加至索引:
设计模式
学习笔记索引
Facade(外观)模式定义了一个高层接口,它能为子系统中的一组接口提供一个一致的界面,从而使得这一子系统更加容易使用。欢迎回到时の魔导士的魔法世界。在对战坏女巫的魔法生物一役中(见Bridge模式笔记),白雪公主获得大逆转胜利机会的关键是附魔武器的诞生。但是,普通的武器工坊(见FactoryMethod模式笔记)生产不了附魔武器,只能是通过特殊的附魔工坊获得。经过这一战之后,大家也觉得除了武器,还需要能保护身体的护甲来抵挡伤害。因此,霍比特人们又打算建立一些护甲工坊。如此一来,用于生产战斗用品的系统就越来越多了。小霍比特人们如果需要获得一整套适合自己的战斗用品,就不得不分别调用每个系统的生产方法。事实上,小霍比特人们并不关心每个系统具体的工作细节,他们只想要得到一件成品而已。对于他们而言,这些生产系统中那些功能强大但层次较低的接口只会使他们的任务复杂化。
为了让小霍比特人们的生活、战斗更便利,好女巫格琳达(Glinda原型请参见《魔境仙踪》,当然,你不会忘记一点:我肯定不会忠于原著)为他们提供了一个高层接口,并且对他们屏蔽了这些生产系统类——格琳达的小屋,在森林里面正式开业了。于是小霍比特人们只需要来到小屋中,告诉Glinda自己需要什么,再付上一点点小酬劳,就可以得到想到的东西啦。
那这一切跟我们今天笔记的主题有什么关系呢?其实这正是Facade模式一个例子,我们将在示例分析部分更加详细地探讨这个问题。首先还是让我们快速地熟悉下什么是Facade模式吧!
要点梳理
目的分类
对象结构型模式
范围准则
对象(该模式处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性)
主要功能
为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
适用情况
当我们要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。
客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
当我们需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,我们可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。
参与部分
Facade:它知道哪些子系统类负责处理请求;它将客户的请求代理给适当的子系统对象。
Subsystem Classes:实现子系统的各种功能;处理由Facade对象指派的任务;不会有Facade的任何相关信息。
协作过程
客户程序通过发送请求给Facade的方式与子系统通讯, Facade将这些消息转发给适当的子系统对象。尽管是子系统中的有关对象在做实际工作,但Facade模式本身也必须将它的接口转换成子系统的接口。
使用Facade的客户程序不需要直接访问子系统对象。
结构图
示例分析 - 格琳达的小屋
在我们前来参观格琳达的小屋之前,不妨先回顾一下那些生产战斗用品的子系统,从而能更好地理解Facade模式工作的机制。由于在Bridge模式笔记中提到Weapon类的设计架构发生了改变,因此包括普通的武器工坊在内的设计也相应地进行了调整。
首先是我们基本的Weapon类:
复制代码
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* cre