zoukankan      html  css  js  c++  java
  • 【PHP设计模式】结构型之门面(facade)

    <意图>
      【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 );
    }
    //检查并存储name
    function getNameFromLine( $line ) {
        if ( preg_match( "/.*-(.*)sd+/", $line, $array ) ) {
            return str_replace( '_',' ', $array[1] );
        }
        return '';
    }
    //检查并存储id
    function 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.<br />';
        }
         //关闭录像机
        public function turnOff() {
            echo 'Turning off the camera.<br />';
        }
        //转到录像机
        public function rotate($degrees) {
            echo 'rotating the camera by ', $degrees, ' degrees.<br />';
        }
    }
    
    class Light {
        //开灯
        public function turnOn() {
            echo 'Turning on the light.<br />';
        }
        //关灯
        public function turnOff() {
            echo 'Turning off the light.<br />';
        }
        //换灯泡
        public function changeBulb() {
            echo 'changing the light-bulb.<br />';
        }
    }
    
    class Sensor {
        //启动感应器
        public function activate() {
            echo 'Activating the sensor.<br />';
        }
        //关闭感应器
        public function deactivate() {
            echo 'Deactivating the sensor.<br />';
        }
        //触发感应器
        public function trigger() {
            echo 'The sensor has been trigged.<br />';
        }
    }
    
    class Alarm {
        //启动警报器
        public function activate() {
            echo 'Activating the alarm.<br />';
        }
        //关闭警报器
        public function deactivate() {
            echo 'Deactivating the alarm.<br />';
        }
        //拉响警报器
        public function ring() {
            echo 'Ring the alarm.<br />';
        }
        //停掉警报器
        public function stopRing() {
            echo 'Stop the alarm.<br />';
        }
    }
    
    //门面类
    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); //只要一个函数就能将调用类简化 
  • 相关阅读:
    javax.servlet.http.HttpServletRequest接口(HTTP版本)
    javax.servlet.http.HttpServletResponse接口(HTTP版本)
    AOP简介AOP是什么?
    javax.servlet.ServletResponse接口(协议无关版本)
    HttpSession接口中的方法(Jsp中的session类的用法)
    网页只允许中国用户访问
    PHP API获取天气预报,以及使用飞信API,给好友发
    php正则表达式抽取email地址函数
    完美解决PHP中文乱码问题
    PHP汉字转换拼音
  • 原文地址:https://www.cnblogs.com/colorstory/p/2721356.html
Copyright © 2011-2022 走看看