金玉其外的门面模式(Facade Pattern)
今天说一个简单易懂的封装模式——门面模式。
<?php interface ILetterProcess{ public function writeContent( $content ); public function fileEnvelope( $address ); public function letterIntoEnvelope(); public function sendLetter(); } class LetterProcessImp implements ILetterProcess{ public function writeContent( $content ) { echo "填写内容:".$content."\n"; } public function fileEnvelope( $address ) { echo "填写收件人地址:".$address."\n"; } public function letterIntoEnvelope() { echo "把信放入信封中\n"; } public function sendLetter() { echo "邮递信件\n"; } } class Safe{ public function checkLetter(ILetterProcess $letterProcess){ echo "信件检查通过"; } }
这有两个类,一个是邮件发送类,一个安全类,现不采用门面模式来发送一个邮件。
$letterProcessImp = new LetterProcessImp(); $safe = new Safe(); $letterProcessImp->writeContent('XXXXX'); $letterProcessImp->fileEnvelope('XXXXX@XX.com'); $safe->checkLetter($letterProcessImp); $letterProcessImp->letterIntoEnvelope(); $letterProcessImp->sendLetter(); 运行结果: 填写内容:XXXXX 填写收件人地址:XXXXX@XX.com 信件检查通过 把信放入信封中 邮递信件 [Finished in 0.2s]
看看这个过程,它与高内聚的要求相差甚远,更不要说迪米特法则、接口隔离原则了。你要知道这几个步骤,并还要知道它们的顺序,一旦出错,信就不可能邮寄出去,这在面向对象的编程中是极度不适合,它根本就没有完成一个类所具有的单一职责。如果有很多信件,那得累死。现在来优化这个过程,利用门面模式来封装,类图如下:
如图所示,增加了一个ModenPostOffice类:
class ModenPostOffice{ private $letterProcess; private $safe; public function __construct(){ $this->letterProcess = new LetterProcessImp(); $this->safe = new Safe(); } public function sendLetter($content,$address){ $this->letterProcess->writeContent($content); $this->letterProcess->fileEnvelope($address); $this->safe->checkLetter($this->letterProcess); $this->letterProcess->letterIntoEnvelope(); $this->letterProcess->sendLetter(); } } $modenPostOffice = new ModenPostOffice(); $modenPostOffice->sendLetter('XXXXX','XXXXX@XX.com'); 运行结果: 填写内容:XXXXX 填写收件人地址:XXXXX@XX.com 信件检查通过 把信放入信封中 邮递信件 [Finished in 0.2s]同上
简化了很多,只要与ModenPostOffice交互就成了,其他什么都不用管。
门面模式的定义
也叫外观模式,是一种比较常用的封装模式。其定义为:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。更简单地说,门面对象是外界访问子系统内部的唯一通道,不管子系统内部是多么杂乱无章,只要有门面对象在,就可以做到“金玉其外,败絮其中”。门面模式由两种角色组成:
1、Facade门面角色
客户端可以调用这个角色的方法。此角色知晓子系统的所有功能和责任。一般情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去,也就说该角色没有实际的业务逻辑,只是一个委托类。
2、subsystem子系统角色
可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另外一个客户端而已。
门面模式的优点
1、减少系统的相互依赖
如果不使用门面模式,外界访问直接深入子系统内部,相互之间是一种强耦合关系,这样的强依赖是系统设计所不能接受的,门面模式很好地解决了这个问题,所有依赖都是对门面对象的依赖,与子系统无关。
2、提高了灵活性
依赖减少了,灵活性自然提高了。不管子系统内部如何变化,只要不影响到门面对象,任由你*活动。
3、提高安全性
想让你访问子系统的哪些业务就开通哪些逻辑,不在门面上开通的方法,你休想访问到。
门面模式的缺点
门面模式最大缺点就是符合开闭原则,对修改关闭,对扩展开放,门面对象是重中之重,一旦在系统上线后发现错误,唯一能做的就是修改门面角色的代码。
门面模式的使用场景
1、为一个复杂的模块或子系统提供一个供外界访问的接口
2、子系统相对独立——外界对子系统的访问只要黑箱操作即可
3、预防低水平人员带来的风险扩散
门面模式的注意事项
1、一个子系统可以有多个门面
(1)门面已经庞大到不能忍受的程度
(2)子系统可以提供不同访问路径
2、门面不参与子系统内的业务逻辑
上一篇: 设计模式(八)--外观模式
推荐阅读
-
聊聊python里如何用Borg pattern实现的单例模式
-
thinkphp5.1框架中容器(Container)和门面(Facade)的实现方法分析
-
一些常用的HTML5模式(pattern) 总结
-
外观模式 门面模式 Facade 创建型 设计模式(十三)
-
解析C#设计模式编程中外观模式Facade Pattern的应用
-
学习php设计模式 php实现门面模式(Facade)
-
设计模式中的facade外观模式在JavaScript开发中的运用
-
Laravel中服务提供者和门面模式的入门介绍
-
外观(门面)模式(Facade Pattern)从最初的代码一步步改进
-
详解PHP中的外观模式facade pattern