根据迪米特法则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。
Facade模式也叫外观模式,是由GoF提出的23种设计模式中的一种。Facade模式为一组具有类似功能的类群,比如类库,子系统等等,提供一个一致的简单的界面。这个一致的简单的界面被称作facade。
个人认为这种模式就是类之间的组合。
外观模式中角色和职责
Façade(外观角色):为调用方, 定义简单的调用接口。
SubSystem(子系统角色):功能提供者。指提供功能的类群(模块或子系统) 。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
/*
外观模式就是将复杂的子类系统抽象到同一个的接口进行管理
,外界只需要通过此接口与子类系统进行交互,而不必要直接与复杂的子类
系统进行交互
*/
//子系统1
class SubSystem1
{
public:
void run()
{
cout << "子系统一运行..." << endl;
}
};
//子系统2
class SubSystem2
{
public:
void run()
{
cout << "子系统二运行..." << endl;
}
};
//子系统3
class SubSystem3
{
public:
void run()
{
cout << "子系统三运行..." << endl;
}
};
//子系统4
class SubSystem4
{
public:
void run()
{
cout << "子系统四运行..." << endl;
}
};
//外观类
class Facede
{
public:
Facede()
{
pSystem1 = new SubSystem1;
pSystem2 = new SubSystem2;
pSystem3 = new SubSystem3;
pSystem4 = new SubSystem4;
}
void runSystem()
{
pSystem1->run();
pSystem2->run();
pSystem3->run();
pSystem4->run();
}
private:
SubSystem1* pSystem1;
SubSystem2* pSystem2;
SubSystem3* pSystem3;
SubSystem4* pSystem4;
};
void test01()
{
Facede* facede = new Facede;
facede->runSystem();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
外观模式案例
根据类图,实现家庭影院外观模式应用。
实现KTV模式:电视打开,灯关掉,音响打开,麦克风打开,dvd打开;
实现游戏模式:电视打开,音响打开,游戏机打开。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//电视
class Television
{
public:
void On()
{
cout << "电视打开!" << endl;
}
void Off()
{
cout << "电视关闭!" << endl;
}
};
//灯
class Lamp
{
public:
void On()
{
cout << "灯打开!" << endl;
}
void Off()
{
cout << "灯关闭!" << endl;
}
};
//音响
class Audio
{
public:
void On()
{
cout << "音响打开!" << endl;
}
void Off()
{
cout << "音响关闭!" << endl;
}
};
//麦克风
class Microphone
{
public:
void On()
{
cout << "麦克风打开!" << endl;
}
void Off()
{
cout << "麦克风关闭!" << endl;
}
};
//DVD播放机
class DVDPlayer
{
public:
void On()
{
cout << "DVDPlayer打开!" << endl;
}
void Off()
{
cout << "DVDPlayer关闭!" << endl;
}
};
//游戏机
class GameMachine
{
public:
void On()
{
cout << "游戏机打开!" << endl;
}
void Off()
{
cout << "游戏界关闭!" << endl;
}
};
//外观抽象类
class AbstractFacede
{
public:
virtual void On() = 0;
virtual void Off() = 0;
};
//游戏模式
class GameMode : public AbstractFacede
{
public:
GameMode()
{
pTelevision = new Television;
pAudio = new Audio;
pGameMachine = new GameMachine;
}
virtual void On()
{
pTelevision->On();
pAudio->On();
pGameMachine->On();
}
virtual void Off()
{
pTelevision->Off();
pAudio->Off();
pGameMachine->Off();
}
private:
Television* pTelevision;
Audio* pAudio;
GameMachine* pGameMachine;
};
//KTV模式
class KTVMode : public AbstractFacede
{
public:
KTVMode()
{
pTelevision = new Television;
pAudio = new Audio;
pDVDPlayer = new DVDPlayer;
pLamp = new Lamp;
pMicrophone = new Microphone;
}
virtual void On()
{
pTelevision->On();
pAudio->On();
pDVDPlayer->On();
pLamp->Off();
pMicrophone->On();
}
virtual void Off()
{
pTelevision->Off();
pAudio->Off();
pDVDPlayer->Off();
pLamp->On();
pMicrophone->Off();
}
private:
Television* pTelevision;
Audio* pAudio;
DVDPlayer* pDVDPlayer;
Lamp* pLamp;
Microphone* pMicrophone;
};
//测试游戏模式和KTV模式
void test01()
{
AbstractFacede* facede = NULL;
facede = new GameMode;
facede->On(); //启动游戏模式
delete facede;
cout << "--------------------------" << endl;
facede = new KTVMode;
facede->On(); //启动KTV模式
delete facede;
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
外观模式的优缺点
优点:
(1)它对客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。通过引入外观模式,客户端代码将变得很简单,与之关联的对象也很少。
(2)它实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可。
(3)一个子系统的修改对其他子系统没有任何影响。
缺点:
(1)不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性。
(2)如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则。
适用场景
(1) 复杂系统需要简单入口使用。
(2) 客户端程序与多个子系统之间存在很大的依赖性。
(3) 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。