委托模式的核心要点

  • 有两个对象参与处理同一个请求。
  • 把接受请求的对象,把请求委托另一个对象处理

举例说明适用场景

1、业务规模变大,原来电商网站只有普通规模。后来增加了用户类型VIP、积分商品结算、增加了合作用户。

2、或者其他非自己的团队开发相同类似的功能。同时进行

为什么要用委托模式?

第一点是解除耦合度,拿下面伪代码举例


class User extends XXXOOO
{
    public $user_role;
    //XXXXOOOO
    //设置一个数据或方法,来区分用户状态
}

假如新增用户类型、那么会不断的更改主类或者继承的基类。主体的类会变得很大

代码栗子

User主类,以User为主。

namespace App\Delegation;


class User
{
    public $name="启东";
    public $gender="男";
    public $user_id=0;
    public $Delegation=null;
    public function __construct($user_id)
    {
        $this->user_id=$user_id;
    }
    public function __call($name, $arguments)
    {
        if($this->Delegation!=null){
            return call_user_func_array([$this->Delegation,$name],$arguments);
        }
        return false;
    }

    function getDiscount()
    {
        return 1;
    }
}

继承了IUserDiscount接口。

namespace App\Delegation;


interface IUserDiscount
{
    function getUserDiscount();
}

UserVip.php

namespace App\Delegation;


class UserVip  implements IUserDiscount
{
    function getUserDiscount():float
    {
        return 0.8;
    }
}

在最理想化的情况,所有开发团队都使用IUserDiscount接口。但也有可能不继承

namespace App\Delegation;


class UserCooperation
{
    public function getCDiscount():float
    {
        return 0.7;
    }
}

调用代码

require "Loader.php";
Loader::init();
use App\Delegation\Product;
use App\Delegation\User;
use App\Delegation\UserVip;
use App\Delegation\UserCooperation;

$product=new Product();
$user_id=101;
$product_id=1;
$user=new User($user_id);
$user->Delegation=new UserVip($user_id);
echo "商品的价格:".$product->getPrice($product_id)*$user->getUserDiscount();
echo PHP_EOL."<br/>".PHP_EOL;

$user->Delegation=new UserCooperation($user_id);
echo "商品的价格:".$product->getPrice($product_id)*$user->getCDiscount();

echo PHP_EOL."<br/>".PHP_EOL;
echo "文件加载数:".Loader::getLoadFileNum();

其他典型例子

例子一

class Color

{
  function callColor()
  {
    print "Generate Red";
  }
}
 

class ColorDelegator

{

  private $targets;

   

  function addObject($obj)

  {

    $this->target[] = $obj;

  }

   

  function __call($name, $args)

  {

    foreach ($this->target as $obj)

    {

      $r = new ReflectionClass($obj);

      if ($method = $r->getMethod($name))

      {

        if ($method->isPublic() &amp;&amp; !$method->isAbstract())

        {
          return $method->invoke($obj, $args);
        }
      }
    }
  }
}

$obj = new ColorDelegator();
$obj->addObject(new Color());
$obj->callColor();

例子二

class Bank{
    protected $info;

    /*
    设置基本信息
    @param string $type 类型。例如"RMB"
    @param int $money 利率。例如"0.4%"
    */
    public function updateBrankInfo($type,$money){
        $this->info[$type]=$money;
    }

    /*
    相关操作(包括存款、取款操作)
    @param int $branktype  操作类型
    */
    public function brankWithdraw($branktype){
        $obj=new $branktype;
        return $obj->brankMain($this->info);
    }
}
/*
委托接口
*/
interface Delegate{
    /*
    操作方法:
    实现该接口必须实现的方法
    */
    public function brankMain($info);
}

/*
存款操作类
*/
class brankDeposit implements Delegate{
    /*
    存款操作
    */
    public function brankMain($info){
        echo $info['deposit'];
    }
} 

/*
取款操作类
*/
class brankWithdraw implements Delegate{
    /*
    取款操作
    */
    public function brankMain($info){
        echo $info['withdraw'];
    }
}
/*
客户端测试代码:
*/
$bank=new Bank();
$bank->updateBrankInfo("deposit","4000");
$bank->updateBrankInfo("withdraw","2000");
$bank->brankWithdraw("brankDeposit");
echo "<br>";
$bank->brankWithdraw("brankWithdraw");

总结

传统模式

委托模式

委托模式意义在于委托两个字,并不一定要继承同一个接口,继承同一个接口那是理想型

参考或更好的文章:https://www.jb51.net/article/79349.htm

Last modification:February 1, 2020
如果觉得我的文章对你有用,请随意赞赏