美文网首页我爱编程
PHP设计模式之委托模式

PHP设计模式之委托模式

作者: flamez57 | 来源:发表于2018-04-06 23:29 被阅读0次

            委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。

            动态委托的介绍:动态委托概念来自于Jakarta 字节码工程库 (Byte-Code Engineering Library, BCEL)。它能够分析存在的类,并且对于接口,抽象类,甚至运行时的具体类来说,它能够生成以字节编码委托类。

            被委托的接口/类应该满足如下条件:动态委托最多只能委托一个类,但是能够代理多个接口。这个限制来自于Java的单继承模式。一个Java类最多只有一个父类。既然生成的委托类把被委托类作为它的父类,那么指定多个被委托类是不合理的。如果没有指定被委托类,那么缺省的父类就是Object。

    书中自有颜如玉,书中自有黄金屋

    下面是PHP 反射机制实现动态代理的代码:

    class Fruit 

    {   

            function callFruit()   

            {    

                    echo "Generate an Apple";  

            } 

    class FruitDelegator

            private $targets;  

            function __construct()  

            {    

                    $this->target[] = new Fruit();  

            }     

            function __call($name, $args)   

            {    

                    foreach ($this->target as $obj)    {      

                            $r = new ReflectionClass($obj);      

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

                                    if ($method->isPublic() && !$method->isAbstract())        {           

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

                                    }       

                            }     

                    }  

            } 

    $obj = new FruitDelegator(); 

    $obj->callFruit(); 

    // 运行结果 

    // Generate an Apple

            可见,通过代理类FruitDelegator来代替Fruit类来实现他的方法。同样的,如下的代码也是能够运行的:

    class Color

    {  

            function callColor()  

            {    

                    echo "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() && !$method->isAbstract())        {          

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

                                    }      

                            }    

                    }  

            }

    }

    $obj = new ColorDelegator();

    $obj->addObject(new Color());

    $obj->callColor();

    书中自有颜如玉,书中自有黄金屋

            设计了一个CD类,类中有mp3播放模式,和mp4播放模式;改进前,使用cd类的播放模式,需要在实例化的类中去判断选择什么方式的播放模式 ;改进后,播放模式当做一个参数传入playList函数中,就自动能找到对应需要播放的方法。

    书中自有颜如玉,书中自有黄金屋

    未改进前

    //使用委托模式之前,调用CD类,选择CD播放模式是复杂的选择过程

    class cd

            protected $cdInfo = array(); 

            public function addSong($song)

            {  

                    $this->cdInfo[$song] = $song; 

            } 

            public function playMp3($song)

            {  

                    return $this->cdInfo[$song] . '.mp3'; 

            } 

            public function playMp4($song)

            {  

                    return $this->cdInfo[$song] . '.mp4'; 

            }

    }

    $oldCd = new cd;

    $oldCd->addSong("1");

    $oldCd->addSong("2");

    $oldCd->addSong("3");

    $type = 'mp3';

    if ($type == 'mp3') { 

            $oldCd->playMp3();

    } else { 

            $oldCd->playMp4();

    }

    书中自有颜如玉,书中自有黄金屋

            通过委托模式,改进后的CD类

    namespace Tools;

    /*

    **委托模式

    **去除核心对象中的判决和复杂功能性

    */

    //委托接口

    interface Delegate

            public function playList($list,$song);

    }

    //mp3处理类

    class mp3 implements Delegate

            public function playList($list,$song)

            {  

                    return $list[$song].'.mp3'; 

            }

    }

    //mp4处理类

    class mp4 implements Delegate

            public function playList($list, $song) 

            {  

                    return $list[$song].'.mp4'; 

            }

    }

    class cdDelegate

            protected $cdInfo = array(); 

            public function addSong($song)

            {  

                    $this->cdInfo[$song] = $song; 

            } 

            public function play($type,$song)

            {  

                    $name = '\Tools\\'.$type;  

                    $obj = new $name;  

                    return $obj->playList($this->cdInfo,$song); 

            }

    }

    $newCd = new cdDelegate();

    $newCd->addSong("1");

    $newCd->addSong("2");

    $newCd->addSong("3");

    echo $newCd->play('mp3','1');

    //只要传递参数就能知道需要选择何种播放模式

    书中自有颜如玉,书中自有黄金屋

    再为大家分享一个实例:

    /** 

    **委托模式 示例 

    */

    class PlayList

            var $_songs = array(); 

            var $_object = null; 

            public function PlayList($type) 

            {  

                    $object = $type."PlayListDelegation";  

                    $this->_object = new $object(); 

            } 

            public function addSong($location,$title) 

            {  

                    $this->_songs[] = array("location"=>$location,"title"=>$title); 

            } 

            public function getPlayList() 

            {  

                    return $this->_object->getPlayList($this->_songs); 

            }

    }

    class mp3PlayListDelegation

            public function getPlayList($songs) 

            {  

                    $aResult = array();  

                    foreach($songs as $key=>$item)  {   

                            $path = pathinfo($item['location']);   

                            if(strtolower($item['extension']) == "mp3")   {    

                                    $aResult[] = $item;   

                            }  

                    }  

                    return $aResult; 

            }

    }

    class rmvbPlayListDelegation

            public function getPlayList($songs) 

            {  

                    $aResult = array();  

                    foreach($songs as $key=>$item)  {   

                            $path = pathinfo($item['location']);   

                            if(strtolower($item['extension']) == "rmvb")   {    

                                    $aResult[] = $item;   

                            }  

                    }  

                    return $aResult; 

            }

    }

    $oMP3PlayList = new PlayList("mp3");

    $oMP3PlayList->getPlayList();

    $oRMVBPlayList = new PlayList("rmvb");

    $oRMVBPlayList->getPlayList();

    书中自有颜如玉,书中自有黄金屋

            图片与文章无关,在阅读技术文档的时候欣赏一下美女也是一个不错的选择,希望可以对你有帮助,如果有错误的地方欢迎指正。

    相关文章

      网友评论

        本文标题:PHP设计模式之委托模式

        本文链接:https://www.haomeiwen.com/subject/zoqehftx.html