4、组合模式

      将对象组合成树形结构表示“部分-整体”的层次结构。
      特点:灵活性强
      应用:对象的部分-整体的层次结构,模糊组合对象和简单对象处理问题

    1. 代码实现<br /> <?php<br /> /**<br /> * 优才网公开课示例代码<br /> *<br /> * 组合模式<br /> *<br /> *@author 优才网全栈工程师教研组<br /> *@see [http://www.ucai.cn](http://www.ucai.cn)<br /> */<br /> //继承模式<br /> class UserBaseInfo {<br /> private$name;<br /> function__construct($name) {<br /> $this->name= $name;<br /> }<br /> public function getName() {<br /> return $this->name;<br /> }<br /> }<br /> class User extends UserBaseInfo {<br /> private$login = false;
    2. public function setLogin($islogin) {<br /> $this->login = $islogin;<br /> }<br /> public function isLogin() {<br /> return $this->login;<br /> }<br /> }<br /> $user = new User('张三');<br /> $user->setLogin(true);<br /> if ($user->isLogin()) {<br /> echo$user->getName()."已经登录了\n";<br /> } else {<br /> echo$user->getName()."还没有登录\n";<br /> }<br /> //组合模式<br /> class LoginInfo {<br /> protected$user;<br /> protected$login = false;
    3. publicfunction setLogin($user, $isLogin) {<br /> $this->user= $user;<br /> $this->login= $isLogin;<br /> }<br /> publicfunction isLogin() {<br /> return$this->login;<br /> }<br /> }<br /> $user = new User('张三');<br /> $login = new LoginInfo();<br /> $login->setLogin($user, true);<br /> if ($login->isLogin()) {<br /> echo$user->getName()."已经登录了\n";<br /> } else {<br /> echo$user->getName()."还没有登录\n";<br /> }<br /> //部分可以更换,用继承则不行<br /> class Admin {<br /> protected$level;<br /> function__construct($level) {<br /> $this->level= $level;<br /> }<br /> functiongetLevel() {<br /> return$this->level;<br /> }<br /> }<br /> $admin = new Admin(1);<br /> $login->setLogin($admin, true);<br /> if ($login->isLogin()) {<br /> printf("级别为 %d 的管理员已经登录了\n",$admin->getLevel());<br /> } else {<br /> printf("级别为 %d 的管理员还没有登录\n",$admin->getLevel());<br /> }<br /> ?><br />  上面的例子分别展示了使用继承和组合来处理新功能,在简单的情况下看似区别不大,但在项目后期越来越复杂的时候组合模式的优势就越来越明显了。

      例如上面的登录信息,如果要增加登录次数、最后登录时间、登录ip等信息,登录本身就会变成一个比较复杂的对象。如果以后有新的需求比如好友信息、用户的访问信息等,再要继承的话,用户类就会变得非常庞大,难免各父类之间没有冲突的变量和方法,而外部访问用户类的众多方法也变得很费劲。采用组合模式后,一个类负责一个角色,功能区分非常明显,扩展方便。

    5、外观模式(门面模式)
      为了系统中的一组接口提供一个一致的界面
      特点:向上抽取,有共性
      应用:内部接口众多,由统一的接口来调用
    <?php
    /*
    优才网公开课示例代码

    外观模式,也叫门面模式

    @author 优才网全栈工程师教研组
    @see http://www.ucai.cn
    /
    class Operation {
    publicfunction testPlus() {
    printf(“plus:%s\n”,(1 + 2 == 3 ? ‘true’ : ‘false’));
    }
    publicfunction testMinus() {
    printf(“minus:%s\n”, (3 - 2 == 2 ? ‘true’ : ‘false’));
    }
    publicfunction testTimes() {
    printf(“times:%s\n”, (2 * 3 == 6 ? ‘true’ : ‘false’));
    }
    }
    class Tester {
    protected$_operation;
    function__construct() {
    $this->_operation= newOperation();
    }
    publicfunction testAll() {
    $this->_operation->testPlus();
    $this->_operation->testMinus();
    $this->_operation->testTimes();
    }
    }
    //测试用例,测试全部接口
    $tester = new Tester();
    $tester->testAll();
    ?>
      门面模式估计大家在实际代码中都已经使用到了,接口较多时把相似功能的接口封装成一个接口供外部调用,这就是门面模式。

    6、享元模式

      运用共享技术有效地支持大量细粒度对象,采用一个共享来避免大量有相同内容对象的开销。这种开销中最直观的就是内存的损耗。
      特点:高效性,共享性
      应用:系统底层的设计。例如字符串的创建。如果两个字符串相同,则不会创建第二个字符串,而是第二个的引用直接指向第一个字符串。$str1=”abc”,$str2=”abc”.则内存存储中只会创建一个字符串“abc”而引用$str1.$str2都会指向它。

    7、代理模式

      为其他对象提供一个代理来控制对这个对象的访问,就是给某一对象提供代理对象,并由代理对象控制具体对象的引用。能够协调调用者和被调用者,能够在一定程度上降低系统的耦合性。
      特点:低耦合性,独立性好,安全性
      应用:客户访问不到或者被访问者希望隐藏自己,所以通过代理来访问自己。

    1. 代码实现<br /> <?php<br /> /**<br /> * 优才网公开课示例代码<br /> *<br /> * 代理模式<br /> *<br /> *@author 优才网全栈工程师教研组<br /> *@see [http://www.ucai.cn](http://www.ucai.cn)<br /> */<br /> //内部对象<br /> class User {<br /> publicfunctiongetName() {<br /> return'张三';<br /> }<br /> publicfunctiongetType() {<br /> return'付费用户';<br /> }<br /> }<br /> //代理接口定义,例如开放平台<br /> interface UserInterface {<br /> functiongetName();<br /> }<br /> //代理对象<br /> class UserProxy implements UserInterface {<br /> protected$_user;<br /> function__construct() {<br /> $this->_user= new User();<br /> }<br /> publicfunctiongetName() {<br /> return$this->_user->getName();<br /> }<br /> }<br /> //内部调用<br /> $user = new User();<br /> printf("user name:%s\n", $user->getName());<br /> printf("user type:%s\n", $user->getType());<br /> //外部调用<br /> // $user = new UserProxy();<br /> // printf("user name:%s\n", $user->getName());<br /> // printf("user type:%s\n", $user->getType()); //不能访问,及时知道内部对象有这个方法<br /> ?>

    三、总结
      代理模式、适配器模式、门面模式、装饰模式的区别
      相同之处:都封装一个内部对象,调用内部对象的方法
      不同之处:各自有各自的特性和应用场景,不能相互替代。所以用的时候要仔细分析用那种合适。

    1. 关于模式的选用问题<br />  模式的选用要根据实际的业务需求,通过对业务逻辑的仔细分析,再根据模式具有的特性和应用场景进行合理的选择和区分。大部分情况下业务的场景决定了哪种模式,而不是选择哪个模式去实现一个业务,少数情况几种模式确实都能解决问题,那主要就是考虑以后的扩展了。

      到这里我们已经了解了7种结构型模式,下一篇我们继续给大家介绍设计模式的行为型模式,先预览一下行为型模式的种类吧:
    模版方法模式
    命令模式
    迭代器模式
    观察者模式
    终结者模式
    备忘录模式
    解释器模式
    状态模式
    策略模式
    职责链模式
    访问者模式

    转自:https://mp.weixin.qq.com/s/7LWjUbo_OCWXz2vMJOsHKw