外观模式
外观模式又称:门面模式、Facade。外观 是一种 结构型设计模式,能为程序库、框架或其他复杂类提供一个简单的接口。这么说你肯定会懵,简单接口?啥???。在面向对象框架中我们使用的各种扩展包,就巧妙的利用了门面模式,大部分拓展包我们都只要引用他的 一个类 就可执行 所有的方法,看拓展包源码你会发现源码文件这么多类?怎么我们使用时只要引入一个类???这其实就是 外观模式,将所有的内部类封装成一个类,供外部使用。
问题
在学校里,我们需要每个班派代表去参加 羽毛球赛,一直都是直接到各个班级去喊人,第二又开展了 乒乓球赛,我们也要去各个班级喊人,而且我们每次喊的人呢?不一定是会打 羽毛球 或者 乒乓球的,我们去喊的时候并不知道我们喊的人会不会 羽毛球 或者 乒乓球。
解决方法
像上述情况耦合非常强,每次我们都要去了解会不会打 羽毛球 或者 乒乓球,而且每次喊的人都需要我们去安排谁先上场,这样我们可能会把实力强的给淹没。解决办法就是我们每个班我们只找班长(门面类),不管是 羽毛球 或 乒乓球,我们找 班长 安排,顺序 也找班长安排,这样我们每次只需要找班长就行,也不要知道班级谁最厉害,谁先上场。班长就是班级的门面,有事找他就对了。
结构
SubSystem: 子系统 示例中指:张三、李四、王五 ; Facade: 外观对象 示例中指:班长 ;
UML
代码示例
班长类
代码语言:javascript复制class MonitorFacade
{
protected $zhansan;
protected $lisi;
protected $wangwu;
public function __construct()
{
$this->zhansan = new ZhangSan();
$this->lisi = new LiSi();
$this->wangwu = new WangWu();
}
public function getName()
{
return '班长';
}
/**
* 羽毛球
* @return string
* @author chendashengpc
*/
public function badminton()
{
return $this->zhansan->getName() .'、'. $this->lisi->getName();
}
/**
* 乒乓球
* @return string
* @author chendashengpc
*/
public function ableTennis()
{
return $this->wangwu->getName() .'、'. $this->lisi->getName();
}
}
班级成员类
张三
代码语言:javascript复制/**
* 张三
*/
class ZhangSan
{
public function getName()
{
return '张三';
}
}
李四
代码语言:javascript复制/**
* 李四
*/
class LiSi
{
public function getName()
{
return '李四';
}
}
王五
代码语言:javascript复制/**
* 王五
*/
class WangWu
{
public function getName()
{
return '王五';
}
}
客户端使用
代码语言:javascript复制/**
* 实例化班长类
*/
$facade = new MonitorFacade();
/**
* 参加乒乓球赛的人员
*/
echo '参加乒乓球赛的人员:' . $facade->ableTennis() . PHP_EOL;
/**
* 参加羽毛球赛人员
*/
echo '参加羽毛球赛人员:' . $facade->badminton() . PHP_EOL;
输出
代码语言:javascript复制参加乒乓球赛的人员:王五、李四
参加羽毛球赛人员:张三、李四
优缺点
优点
- 可以让代码独立于复杂子系统。
缺点
- 外观可能成为与程序中所有类都耦合的上帝对象。(班级离开班长就无计可施了)