12. 代理模式

这里写图片描述

//传统方法
$db = IMooc\Factory::getDatabase('slave');
$info = $db->query('select name from user where id=1 limit 1');

$db1 = IMooc\Factory::getDatabase('master');
$info = $db->query("update user name='lili' where id=1 limit 1");

index.php

//不再直接去操作数据库,而是先创建代理对象
$proxy = new IMooc\Proxy();
//这样在代码中就看不到对数据库的存取实际的位置
$proxy->getUserName($id);
$proxy->setUserName($id,$proxy);

Proxy.php

<?php

namespace IMooc;

class Proxy implements IUserProxy
{
    //表示读操作
    public function getUserName($id)
    {
        $db = Factory::getDatabase('slave');
        $db->query("select name from user where id=$id limit 1");
    }

    //表示写操作
    public function setUserName($id,$name)
    {
        $db = Factory::getDatabase('master');
        $db->query("select user set name=$name where id=$id limit 1");
    }
}

IUserProxy.php

<?php

namespace IMooc;

interface IUserProxy
{
    public function getUserName($id);
    public function setUserName($id,$name);
}

PHP的代理模式
代理模式与父类和接口的异同

相同点:代理模式的作用和父类以及接口和组合的作用类似,都是为了聚合共用部分,减少公共部分的代码
不同点:
相比起父类,他们的语境不同,父类要表达的含义是 is-a, 而代理要表达的含义更接近于接口, 是 has-a,而且使用代理的话应了一句话"少用继承,多用组合",要表达的意思其实也就是降低耦合度了
相比起接口,他们实现的功能又不太一样,语境都是has-a,不过接口是has-a-function,而代理对象时是has-a-object,这个object是has-a-function的object,此外,接口是为了说明这个类拥有什么功能,却没有具体实现,实现了多态,而代理对象不但拥有这个功能,还拥有这个功能的具体实现
对于组合来说,他比组合更具灵活性,比如我们将代理对象设为private,那么我可以选择只提供一部分的代理功能,例如Printer的某一个或两个方法,又或者在提供Printer的功能的时候加入一些其他的操作,这些都是可以的
<?php

class Printer   //代理对象,一台打印机
{
    public function printSth()
    {
        echo 'Printer<br/>';
    }
}

class TestShop    //这是一个文印处理店,只文印,卖纸,不照相
{
    private $printer;

    public function __construct(Printer $printer)
    {
        $this->printer = $printer;
    }

    public function sellPaper()
    {
        echo 'sell Paper<br/>';
    }

    public function __call($method,$args)  //将代理对象有的功能交给代理对象处理
    {
        if(method_exists($this->printer, $method))
        {
           $this->printer->$method($args);
        }
    }
}

class PhotoShop   //这是一个照相店,只文印,拍照,不卖纸
{
//这是一个照相店,只文印,拍照,不卖纸
     private $printer;

    public function __construct(Printer $printer) {
        $this->printer = $printer;
    }

    public function takePhotos() {    //照相 
        echo 'take photos for you <br/>';
    }

    public function __call($method, $args) {    //将代理对象有的功能交给代理对象处理
        if(method_exists($this->printer, $method)) {
            $this->printer->$method($args);
        }
    }
}

$printer = new Printer();
$textShop = new TestShop($printer);
$photoShop = new PhotoShop($printer);

$textShop->printSth();
$photoShop->printSth();
文印处理店和照相店都具有文印的功能,所以我们可以将文印的功能代理给一台打印机,这里打印机只有一个功能,假如打印机还有n个功能,我们使用__call()方法就能够省去很多重复的代码了

假如是使用继承,这样语境上就不合理,一个店显然不应该继承一台打印机

而使用接口,因为我们的功能实现都是一样,也没有必要去重新实现接口的功能

所以此处使用代理是最佳选择
代理模式是把难复制的、占资源多的、远程速度慢的对象,各自对应一个代理对象,被代理后进行本地的操作。对每个被代理的对象,都可以进行本地的个性化扩展。使一些不够完善的对象更加好的适应本地操作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值