zoukankan      html  css  js  c++  java
  • 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;
  • 相关阅读:
    剑指offer——最小的K个数和数组中第K大的元素
    Leetcode刷题指南链接整理
    160. Intersection of Two Linked Lists
    100. Same Tree
    92. Reverse Linked List II
    94. Binary Tree Inorder Traversal
    79. Word Search
    78,90,Subsets,46,47,Permutations,39,40 DFS 大合集
    0x16 Tire之最大的异或对
    0x16 Tire
  • 原文地址:https://www.cnblogs.com/HKUI/p/4306209.html
Copyright © 2011-2022 走看看