定义
外观模式提供了一个统一的接口,用来访问子系统种的一群接口。外观定义了一个高层接口,让子系统更容易使用。
有时候我们创建一个接口简化而统一的类,用来包装子系统种的一个或多个复杂的类。它允许我们让客户和子系统之间避免紧耦合。
UML类图
上图中各个部分组成如下:
外观角色类(Facade):客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
子系统:实现子系统的功能,并处理由Facade对象指派的任务。对子系统而言,facade和client角色是未知的,没有Facade的任何相关信息;即没有指向Facade的实例。
客户端:通过调用facade对象接口实现调用各个子系统接口的功能
#ifndef _FACADE_H_
#define _FACEDE_H_
#include <iostream>
#include <memory>
class System1
{
public:
void Operation()
{
std::cout << "System1 Operation" << std::endl;
}
};
class System2
{
public:
void Operation()
{
std::cout << "System2 Operation" << std::endl;
}
};
class Facade
{
public:
Facade(std::shared_ptr<System1> p1, std::shared_ptr<System2> p2) : system1_p(p1), system2_p(p2)
{
}
virtual ~Facade()
{
}
std::shared_ptr getpSystem1() const
{
return system1_p;
}
std::shared_ptr getpSystem2() const
{
return system2_p;
}
void OperationWrapper()
{
if(system1_p) system1_p->Operation();
if(system2_p) system2_p->Operation();
}
private:
std::shared_ptr<System1> system1_p;
std::shared_ptr<System2> system2_p;
};
#endif
#include <iostream>
#include <memory>
#include "Facade.h"
using namespace std;
int main()
{
std::shared_ptr<System1> pSystem1 = std::make_shared<System1>();
std::shared_ptr<System2> pSystem2 = std::make_shared<System2>();
if(!pSystem1 || !pSystem2)
return 0;
Facade facade(pSystem1, pSystem2);
facade.OperationWrapper();
return 0;
}
结果图
最少知识原则:
使用外观模式德时候,需要注意一个原则,就是最少知识原则,也就是在设计接口的时候,当你正在设计一个系统,不管是任何对象,你都要注意它所交互的类有哪些,并注意这些类是如何交互的。这个原则希望我们在设计中,不要让太对的类,耦合在一起,避免修改系统中的一部分,会影响其他部分。对本例子来说,可能有些子系统是其他几类子系统的facade,暂且认为是subFacade,对Facade而言不必,理会SubFacade下的子系统的细节。
在实际应用中经常会出现这样一个方法:放在本类中也可以,放在其他类中也没有问题,怎么去衡量呢?建议:如果一个类放在本类中,既不增加类间关系,又不对本类产生不负面影响,就放置在本类中。
- 在类的划分上,应该创建有弱耦合的类
- 在类的结构设计上,每一个类都应当尽量降低成员的访问权限
- 在类的设计上,只要有可能,一个类应当设计成不变类,防止类的行为被篡改
- 在对其他类的引用上,一个对象对其它对象的引用应当降到最低
- 尽量降低类的访问权限
- 不要暴露类成员,而应该提供相应的访问器(属性),
优点
- 类负责的职责清晰明了,使类可以高度内聚降低类与类之间的耦合
缺点
- 更多的包装类被制造出来,以处理和其他组件的沟通,从而导致工程复杂度和开发时间的增加,也会降低运行时的性能。
class House
{
public:
House(std::shared_ptr<WeatherStation> pStation) : station_p(pStation){}
float getTemp()
{
station_p->getThermometer().getTemperature();
}
std::shared_ptr<WeatherStation> station_p;
}
上述代码就不符合最少知识原则,应该在WeatherStation设计返回getTemp()的接口,避免将WeatherStation下的组成类成员的细节暴露给House