博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP设计模式:结构型之门面(facade)
阅读量:5065 次
发布时间:2019-06-12

本文共 6089 字,大约阅读时间需要 20 分钟。

<意图>

  【GOF】为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层次的接口,使得子系统更加容易使用。

  外部与子系统的通信是通过一个门面(Facade)对象进行。

门面模式:

  外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。

<UML>

【门面模式的优点】

1、它对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便
2、实现了子系统与客户之间的松耦合关系
3、如果应用需要,它并不限制它们使用子系统类。因此可以在系统易用性与能用性之间加以选择

【门面模式适用场景】

1、为一些复杂的子系统提供一组接口
2、提高子系统的独立性
3、在层次化结构中,可以使用门面模式定义系统的每一层的接口

【门面模式与其它模式】

抽象工厂模式:Abstract Factory模式可以与Facade模式一起使用以提供一个接口,这一接口可用来以一种子系统独立的方式创建子系统对象。Abstract Factory模式也可以代替Facade模式隐藏那些与平台相关的类
调停者模式:Mediator模式与Facade模式的相似之处是,它抽象了一些已有类的功能。然而,Mediator目的是对同事之间的任意通讯进行抽象,通常集中不属于任何单个对象的功能。Mediator的同事对象知道中介者并与它通信,而不是直接与其他同类对象通信。相对而言,Facade模式仅对子系统对象的接口进行抽象,从而使它们更容易使用;它并定义不功能,子系统也不知道facade的存在
单例模式:一般来说,仅需要一个Facade对象,因此Facade对象通常属于Singleton对象。

<示例一>获取文件中的log信息并转换成对象数组

//获取文件的内容function getProductFileLines( $file ) {    return file( $file );}function getProductObjectFromId( $id, $productname ) {    return new Product( $id, $productname );}//检查并存储namefunction getNameFromLine( $line ) {    if ( preg_match( "/.*-(.*)\s\d+/", $line, $array ) ) {        return str_replace( '_',' ', $array[1] );    }    return '';}//检查并存储idfunction getIDFromLine( $line ) {    if ( preg_match( "/^(\d{1,3})-/", $line, $array ) ) {        return $array[1];    }    return -1;}class Product {    public $id;    public $name;    function __construct( $id, $name ) {        $this->id = $id;        $this->name = $name;    }}$lines = getProductFileLines( 'test.txt' );$objects = array();foreach ( $lines as $line ) {    $id = getIDFromLine( $line );    $name = getNameFromLine( $line );    $objects[$id] = getProductObjectFromID( $id, $name  );}print_r( $objects );

  <UML>

  此时的结构如上图所示。获取文件内容并检查转换成对象数组是个复杂的过程,我们的客户端代码和子系统将会仅仅地耦合在一起。当子系统变化时,或者我们决定将子系统断开时,代码就会出现问题。因此我们的做法应该是在客户端和子系统代码中间建立一个入口。

class ProductFacade {    private $products = array();    function __construct( $file ) {        $this->file = $file;        $this->compile();    }    private function compile() {        $lines = getProductFileLines( $this->file );        foreach ( $lines as $line ) {            $id = getIDFromLine( $line );            $name = getNameFromLine( $line );            $this->products[$id] = getProductObjectFromID( $id, $name  );        }    }     function getProducts() {        return $this->products;    }    function getProduct( $id ) {        return $this->products[$id];    }}$facade = new ProductFacade( 'test.txt' );print_r( $facade->getProducts() );print_r( $facade->getProduct(234) );

<UML>

此时的客户端代码只需要通过门面ProductFacade对象就可以调用了。

<示例二>

class Camera {    //打开录像机    public function turnOn() {        echo 'Turning on the camera.
'; } //关闭录像机 public function turnOff() { echo 'Turning off the camera.
'; } //转到录像机 public function rotate($degrees) { echo 'rotating the camera by ', $degrees, ' degrees.
'; }}class Light { //开灯 public function turnOn() { echo 'Turning on the light.
'; } //关灯 public function turnOff() { echo 'Turning off the light.
'; } //换灯泡 public function changeBulb() { echo 'changing the light-bulb.
'; }}class Sensor { //启动感应器 public function activate() { echo 'Activating the sensor.
'; } //关闭感应器 public function deactivate() { echo 'Deactivating the sensor.
'; } //触发感应器 public function trigger() { echo 'The sensor has been trigged.
'; }}class Alarm { //启动警报器 public function activate() { echo 'Activating the alarm.
'; } //关闭警报器 public function deactivate() { echo 'Deactivating the alarm.
'; } //拉响警报器 public function ring() { echo 'Ring the alarm.
'; } //停掉警报器 public function stopRing() { echo 'Stop the alarm.
'; }}//门面类class SecurityFacade { /* 录像机 */ private $_camera1, $_camera2; /* 灯 */ private $_light1, $_light2, $_light3; /* 感应器 */ private $_sensor; /* 警报器 */ private $_alarm; public function __construct() { $this->_camera1 = new Camera(); $this->_camera2 = new Camera(); $this->_light1 = new Light(); $this->_light2 = new Light(); $this->_light3 = new Light(); $this->_sensor = new Sensor(); $this->_alarm = new Alarm(); } public function activate() { $this->_camera1->turnOn(); $this->_camera2->turnOn(); $this->_light1->turnOn(); $this->_light2->turnOn(); $this->_light3->turnOn(); $this->_sensor->activate(); $this->_alarm->activate(); } public function deactivate() { $this->_camera1->turnOff(); $this->_camera2->turnOff(); $this->_light1->turnOff(); $this->_light2->turnOff(); $this->_light3->turnOff(); $this->_sensor->deactivate(); $this->_alarm->deactivate(); }}//客户端class Client { private static $_security; public static function main() { self::$_security = new SecurityFacade(); self::$_security->activate(); }}Client::main();

<结果>

Turning on the camera.Turning on the camera.Turning on the light.Turning on the light.Turning on the light.Activating the sensor.Activating the alarm.

 

外观模式:为复杂或多边的系统创建一个简单的接口。

class User {          protected $userName;     protected $userAge;          public function setUserName($userName) {         return $this->userName = $userName;     }          public function setUserAge($userAge) {         return $this->userAge = $userAge;     }          public function getUser() {         echo '用户姓名:' . $this->userName . '; 用户年龄:' . $this->userAge;     } }

 

代码:UserFacade 用户类外观接口,一个getUserCall接口

//创建一个User 类调用接口,简化获取用户getUser方法的调用 

class UserFacade {     public static function getUserCall($userInfo) {         $User = new User;         $User->setUserName($userInfo['username']);         $User->setUserAge($userInfo['userAge']);         return $User->getUser();     } }

调用:调用的具体执行在外观类中执行,外观类返回一个可以供客户调用的简洁方法,用来获取所需的数据。

$userInfo = array('username' => 'initphp', 'userAge' => 12); UserFacade::getUserCall($userInfo); //只要一个函数就能将调用类简化

转载于:https://www.cnblogs.com/colorstory/p/2721356.html

你可能感兴趣的文章
mysqladmin
查看>>
解决 No Entity Framework provider found for the ADO.NET provider
查看>>
设置虚拟机虚拟机中fedora上网配置-bridge连接方式(图解)
查看>>
[置顶] Android仿人人客户端(v5.7.1)——人人授权访问界面
查看>>
Eclipse 调试的时候Tomcat报错启动不了
查看>>
ES6内置方法find 和 filter的区别在哪
查看>>
Android实现 ScrollView + ListView无滚动条滚动
查看>>
java学习笔记之String类
查看>>
UVA 11082 Matrix Decompressing 矩阵解压(最大流,经典)
查看>>
jdk从1.8降到jdk1.7失败
查看>>
硬件笔记之Thinkpad T470P更换2K屏幕
查看>>
iOS开发——缩放图片
查看>>
HTTP之URL的快捷方式
查看>>
满世界都是图论
查看>>
配置链路聚合中极小错误——失之毫厘谬以千里
查看>>
代码整洁
查看>>
蓝桥杯-分小组-java
查看>>
Android Toast
查看>>
iOS开发UI篇—Quartz2D使用(绘制基本图形)
查看>>
docker固定IP地址重启不变
查看>>