• php设计模式之Proxy(代理模式)和Facade(外观)设计模式


    Proxy(代理模式)和Facade(外观)设计模式
    它们均为更复杂的功能提供抽象化的概念,但这两种实现抽象化的过程大不相同

    Proxy案例中,所有的方法和成员变量都来自于目标对象,必要时,该代理能够对它所传递的数据进行修改或检查
    魔术方法使得Proxy的实现变的简单,Proxy模式的一类应用时用来记录方法的访问信息
    还可以利用Proxy的类确定代码的范围或调试程序中存在的问题

    <?php
    class LoggingProxy{
        private $target;
        //传递进去一个对象
        public function __construct($target){
            $this->target=$target;
        }
        protected function log($line){
            echo "[".$line."]
    ";
        }
        public function __set($name,$value){
            $this->target->$name=$value;
            $this->log("setting value for $name:$value ");
        }
        public function __get($name){
            $value=$this->target->$name;
            $this->log("Getting value for $name:$value");
            return $value;
        }
        public function __isset($name){
            $value=isset($this->target->$name);
            $this->log("checking isset for $name".($value?"true":"false"));
            return $value;
        }
        public function __call($name,$arguments){
            $this->log("calling method $name ".implode(",", $arguments));
            return call_user_func_array(array($this->target,$name), $arguments);
            
        }
    }
    class People{
        public $name='hk';
        public $age;
        public function sayname(){
            return $this->name;
        }
        public function plus($a,$b){
            return $a+$b;
        }
    }
    $p=new People();
    $proxy=new LoggingProxy($p);
    echo $proxy->name;//hk
    echo "<br>";
    $proxy->age=10;
    echo $p->age;//10
    echo "<br>";
    echo $proxy->sayname();
    echo "<br>";
    echo $proxy->plus(2,3);

    结果

    [Getting value for name:hk] hk
    [setting value for age:10 ] 10
    [calling method sayname ] hk
    [calling method plus 2,3] 5

    多数情况下Proxy不应该改变它所代理的类的行为
    Proxy与它所代理的在类型上不完全一致,这也是其一个缺点。
    因而若需要进行类型提示或代码检查以确保对象是某一特定类型,这种情况下就不能使用代理模式


    Facade(外观)模式提供了不同的功能,用来抽象化复杂功能,以使应用程序无需了解子系统处理
    各请求的细节,就能完成整个处理过程
    例如:处理典型api请求时,用户需要通过子系统进行认证,认证通过后,请求通过api子系统传递给远程服务器
    处理,最后通过其它api的函数对相应解码
    Facade方法粗略实现如下

    <?php
    class Facade{
        public function apiRequestJson($method,$parameters){
            $user=User::getAuthenticatedUser();
            if($user->hasPermission($method)){
                $result=$this->api->$method($parameters);
                return json_encode($result);
            }
        }
    }

    Facade并不为子系统添加任何新的功能,而是为子系统委托合适的责任。
    子系统无需知道Facade的存在,而应用程序也无需知道子系统的存在。

    下面代码,没使用外观模式前

    <?php
    function getProductFileLines($file){
        return file($file);
    }
    function getProductObjectFromId($id,$productname){
        return new Product($id,$productname);
    }
    
    function getNameFromLine($line){
        if(preg_match('#.*-(.*)sd+#', $line,$array)){
            return str_replace('_', ' ', $array[1]);
        }
        return '';
    }
    function getIdFromLine($line){
        if(preg_match('#^(d{1,3})-#', $line,$arr)){
            return $arr[1];
        }
        return -1;
    }
    class Product{
        public $id;
        public $name;
        public function __construct($id,$name){
            $this->id=$id;
            $this->name=$name;
        }
    }
    
    $lines=getProductFileLines('t.txt');
    $objects=array();
    foreach ($lines as $line){
        $id=getIdFromLine($line);
        $name=getNameFromLine($line);
        $objects[$id]=getProductObjectFromId($id, $name);
    }

    t.txt内容

    234-ladies_jumper  55
    532-gents_hat  44

    如果像以上代码调用子系统,我们的代码和子系统紧紧耦合在一起,当子系统变化时,或者我们决定将其与子系统完全断开时,代码就会出问题,所以我们需要在

    这些子系统和代码中引入一个入口。

    class ProductFacade{
        private $products=array();
        public 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);
            }
        }
        public function getProducts(){
            return $this->products;
        }
        public function getProduct($id){
            return $this->products[$id];
        }
    }
    
    $facade=new ProductFacade('t.txt');
    echo $facade->getProduct(234)->name;
  • 相关阅读:
    人月神话阅读笔记(三)
    MongoDB设置用户名以及密码
    pdf.js使用总结#如何在网页读取并显示PDF格式文档
    Python中eval函数的作用
    寒假学习笔记(13)
    寒假学习笔记(12)
    寒假学习笔记(11)
    寒假学习笔记(10)
    寒假学习笔记(9)
    寒假学习笔记(8)
  • 原文地址:https://www.cnblogs.com/HKUI/p/4306209.html
Copyright © 2020-2023  润新知