如何学PHP设计模式之委托者模式和策略模式的区别

看《PHP设计模式》这本书,里面写到委托模式和策略模式,我翻来覆去的看,从代码上看它们是一种东西,至少实现的原理是一样的。

搜了百度、谷歌、bing,对于委托模式资料很少,勉强自己总结了一下:

委托模式:当一个对象在不同的情况下需要调用不同的方法,而这些方法自己本身没有实现,就可以通过委托的方式来让其他对象来做。

策略模式:当一个类里某个方法在不同的情况下需要不同的算法实现,这时候可以用策略模式。

先说委托模式,我们假设有一个公司职员的基类Person基类里包含了基本的方法,比如获取员工的姓名、年龄等。但是员工有不同的角色,比如后端工程师、前端工程师、项目经理,一般情况下我们想要获取后端工程师特有的数据,会想到用继承的方式,如果场景固定,可以这么做,但有时候一个人可能同时身兼多种角色,这时候你需要添加”后端and经理” “前端and后端” 等等组合,角色越多问题越大,最后你会发现无尽的继承。委托模式这时候就可以派上用场了可以动态的切换角色,直接看代码吧:

<?php
class Person {
    public $age;
    public $name;
    private $_delegator;
    //获取出勤记录
    public function getAttendance(){
        ...
    }
    
    //以上都是公共方法
    ...
    
    //注册委托者
    function setDelegator($delegator){
        $this->_delegator = $delegator;
    }
    //调用委托者的方法
    function invokeDelegator($method,$params=array()){
        array_unshift($params,$this);//使委托者对象能够调用Person对象的属性和方法
        return call_user_func_array(array($this->_delegator,$method),$params);
    }   
}

//项目经理类
class Manager{
    //获取会议记录
    function meeting($person){
         ...
         return $data;
    }
}

//工程师类
class Engineer{
    //获取项目列表
    function projectList($person){
         ...
         return $data;
    }
}


$person = new Person();
$person->name = "张三";
$person->age = 34;
//获取张三作为项目经理的工龄
$person->setDelegator(new Manager());
$meeting = $person->invokeDelegator("meeting");//获取项目经理的会议记录
//角色切换到工程师
$person->setDelegator(new Engineer());
$projectList = $person->invokeDelegator("projectList");//获取工程师的项目列表

这样,我们就不用将项目经理、工程师都去继承person类,而且可以动态切换角色,并且避免了过度继承造成的类爆炸。

再看看策略模式:

策略模式是当某个类中某一个方法可能在不同的情形下需要有不同的算法,比如一个唱片CD类,其中有一个方法是getList()获取唱片列表,客户A可能需要的是json格式,客户B可能需要的是xml格式,这时候就需要为getList就难以满足这些变化的需求,策略模式可以解决这个问题。

<?php
class CD {
   public $list;//列表源数据,数组模式
   function getList($list_maker){
       return $list_maker->getList($list);
   }
}

class Json {
   function getList($list){
      return json_encode($list);
   }

}


class Xml {
   function getList($list){
      ...
      return $xml->saveXml();
   }
}


$CD = new CD();
$jsonlist = $CD->getList(new Json());//json格式的列表
$xmllist = $CD->getList(new Xml());//获取xml格式的列表

与委托模式的区别主要是理念上的,我们CD类本身是有getList这个功能的,只是后来根据不同的情景需要有不同的算法,我们只是把switch…case…封装出去了:Json、Xml……

我想,大概就是如此了吧。

转载至链接:https://my.oschina.net/cxz001/blog/267087

(0)
上一篇 2019年3月27日 下午10:53
下一篇 2019年3月29日 下午6:12

相关推荐

发表回复

登录后才能评论