zoukankan      html  css  js  c++  java
  • 常用设计模式详解

    设计模式的作用:一方面将变化的东西封装起来,另一方面将众多的类抽象开防止类过多

    1、简单工厂模式

    不同条件下创建不同实例

    2、抽象工厂模式

    简单工厂模式有个问题,每添加一次新的类都要修改方法,不符合面向对象的开闭原则(对类的增加开放,对类的修改闭合)

    抽象工厂模式便解决了这一问题,每次添加新的类就行了。

    3、单例模式

    保证一个类仅有一个实例

    <?php
    namespace Test;
    
    class Database
    {
       //私有化内部实例化的对象
        private static $instance = null;
       //私有化构造方法,禁止外部实例化
        private function __construct(){}
        //私有化__clone,防止被克隆
        private function __clone(){}
        // 公有静态实例方法
        public static function getInstance(){
           if(empty(self::$instance)){
                  self::$instance=new Test();
               }
               return self::$instance;
           }
        }
    
    $obj1=Test::getInstance();
    $obj2=Test::getInstance();
    echo $obj1==$obj2?1:0;

    4、观察者模式

    一对多的依赖关系,在观察目标类里有一个 ArrayList 存放观察者们。当观察目标对象的状态发生改变,所有依赖于它的观察者都将得到通知,使这些观察者能够自动更新(即使用推送方式) 

    主题提供注册和通知的接口,观察者提供自身操作的接口。(这些观察者拥有一个同一个接口。)观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。耦合度相当之低。

    如何实现观察者注册?通过前面的注册者模式很容易给我们提供思路,把这些对象加到一棵注册树上就好了嘛。如何通知?这就更简单了,对注册树进行遍历,让每个对象实现其接口提供的操作。

    <?php
    // 主题接口
    interface Subject{
        public function register(Observer $observer);
        public function notify();
    }
    // 观察者接口
    interface Observer{
        public function watch();
    }
    // 主题
    class Action implements Subject{
         public $_observers=array();
         public function register(Observer $observer){
             $this->_observers[]=$observer;
         }
    
         public function notify(){
             foreach ($this->_observers as $observer) {
                 $observer->watch();
             }
    
         }
     }
    
    // 观察者
    class Cat implements Observer{
         public function watch(){
             echo "Cat watches TV<hr/>";
         }
     } 
     class Dog implements Observer{
         public function watch(){
             echo "Dog watches TV<hr/>";
         }
     } 
     class People implements Observer{
         public function watch(){
             echo "People watches TV<hr/>";
         }
     }
    
    
    
    // 应用实例
    $action=new Action();
    $action->register(new Cat());
    $action->register(new People());
    $action->register(new Dog());
    $action->notify();

    5、责任链模式

     拦截的类都实现统一接口,每个接收者都包含对下一个接收者的引用。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

    <?php   
      
    //申请Model  
    class Request  
    {  
        //数量  
        public $num;  
        //申请类型  
        public $requestType;  
        //申请内容  
        public $requestContent;  
    }  
      
    //抽象管理者  
    abstract class Manager  
    {  
        protected $name;  
        //管理者上级  
        protected $manager;  
        public function __construct($_name)  
        {  
            $this->name = $_name;  
        }  
      
        //设置管理者上级  
        public function SetHeader(Manager $_mana)  
        {  
            $this->manager = $_mana;  
        }  
      
        //申请请求  
        abstract public function Apply(Request $_req);  
      
    }  
      
    //经理  
    class CommonManager extends Manager  
    {  
        public function __construct($_name)  
        {  
            parent::__construct($_name);  
        }  
        public function Apply(Request $_req)  
        {  
            if($_req->requestType=="请假" && $_req->num<=2)  
            {  
                echo "{$this->name}:{$_req->requestContent} 数量{$_req->num}被批准。<br/>";  
            }  
            else  
            {  
                if(isset($this->manager))  
                {  
                    $this->manager->Apply($_req);  
                }  
            }  
      
        }  
    }  
      
    //总监  
    class MajorDomo extends Manager  
    {  
        public function __construct($_name)  
        {  
            parent::__construct($_name);  
        }  
      
        public function Apply(Request $_req)  
        {  
            if ($_req->requestType == "请假" && $_req->num <= 5)  
            {  
                echo "{$this->name}:{$_req->requestContent} 数量{$_req->num}被批准。<br/>";  
            }  
            else  
            {  
                if (isset($this->manager))  
                {  
                    $this->manager->Apply($_req);  
                }  
            }  
      
        }  
    }  
      
      
    //总经理  
    class GeneralManager extends Manager  
    {  
        public function __construct($_name)  
        {  
            parent::__construct($_name);  
        }  
      
        public function Apply(Request $_req)  
        {  
            if ($_req->requestType == "请假")  
            {  
                echo "{$this->name}:{$_req->requestContent} 数量{$_req->num}被批准。<br/>";  
            }  
            else if($_req->requestType=="加薪" && $_req->num <= 500)  
            {  
                echo "{$this->name}:{$_req->requestContent} 数量{$_req->num}被批准。<br/>";  
            }  
            else if($_req->requestType=="加薪" && $_req->num>500)  
            {  
                echo "{$this->name}:{$_req->requestContent} 数量{$_req->num}再说吧。<br/>";  
            }  
        }  
    }    

    调用:

    header("Content-Type:text/html;charset=utf-8");  
    //--------------------职责链模式----------------------  
    require_once "./Responsibility/Responsibility.php";  
    $jingli = new CommonManager("李经理");  
    $zongjian = new MajorDomo("郭总监");  
    $zongjingli = new GeneralManager("孙总");  
      
    //设置直接上级  
    $jingli->SetHeader($zongjian);  
    $zongjian->SetHeader($zongjingli);  
      
    //申请  
    $req1 = new Request();  
    $req1->requestType = "请假";  
    $req1->requestContent = "小菜请假!";  
    $req1->num = 1;  
    $jingli->Apply($req1);  
      
    $req2 = new Request();  
    $req2->requestType = "请假";  
    $req2->requestContent = "小菜请假!";  
    $req2->num = 4;  
    $jingli->Apply($req2);  
      
    $req3 = new Request();  
    $req3->requestType = "加薪";  
    $req3->requestContent = "小菜请求加薪!";  
    $req3->num = 500;  
    $jingli->Apply($req3);  
      
    $req4 = new Request();  
    $req4->requestType = "加薪";  
    $req4->requestContent = "小菜请求加薪!";  
    $req4->num = 1000;  
    $jingli->Apply($req4);  
    

      

    6、策略模式

    策略对象依赖注入到context对象,context对象根据它的策略改变而改变它的相关行为(可通过调用内部的策略对象实现相应的具体策略行为) 

    <?php
    header('Content-Type:text/html;charset=utf-8');
    /**
     * 策略模式演示代码
     *
     * 为了更好地突出“策略”,我们这里以出行为例演示,日常出行大概分为以下几种工具:自驾车,公交车,地铁,火车,飞机,轮船
     *
     * 下面一起看代码,领会何为策略模式
     */
    
    /**
     * Interface Travel 抽象策略角色
     * 约定具体方法
     */
    interface Travel
    {
        public function go();
    }
    
    /**
     * Class selfDriving 具体策略角色
     * 自驾车
     */
    class bySelfDriving implements Travel
    {
        public function go()
        {
            echo '我自己开着车出去玩<br>';
        }
    }
    
    /**
     * Class byBus具体策略角色
     * 乘公交
     */
    class byBus implements Travel {
        public function go()
        {
            echo '我乘公交出去玩<br>';
        }
    }
    
    /**
     * Class byMetro 具体策略角色
     * 乘地铁
     */
    class byMetro implements Travel
    {
        public function go()
        {
            echo '我乘地铁出去玩<br>';
        }
    }
    
    /**
     * Class byTrain 具体策略角色
     * 乘火车
     */
    class byTrain implements Travel
    {
        public function go()
        {
            echo '我乘火车出去玩<br>';
        }
    }
    
    /**
     * Class byAirplane 具体策略角色
     * 乘飞机
     */
    class byAirplane implements Travel
    {
        public function go()
        {
            echo '我乘飞机出去玩<br>';
        }
    }
    
    /**
     * Class bySteamship 具体策略角色
     * 乘轮船
     */
    class bySteamship implements Travel
    {
        public function go()
        {
            echo '我乘轮船出去玩<br>';
        }
    }
    
    /**
     * Class Mine 环境角色
     */
    class Mine{
        private $_strategy;
        private $_isChange = false;
    
        /**
         * 构造方法
         * 此处使用到了依赖注入和类型约束的概念,详情请参考
         * 1.聊一聊PHP的依赖注入(DI) 和 控制反转(IoC)
         * @link https://segmentfault.com/a/1190000007209266
         * 2.浅谈PHP的类型约束
         * @link https://segmentfault.com/a/1190000007226476
         *
         * @param Travel $travel
         */
        public function __construct(Travel $travel)
        {
            $this->_strategy = $travel;
        }
    
        /**
         * 改变出行方式
         *
         * @param Travel $travel
         */
        public function change(Travel $travel)
        {
            $this->_strategy = $travel;
            $this->_isChange = true;
        }
    
        public function goTravel()
        {
            if ($this->_isChange) {
                echo '现在改变主意,';
                $this->_strategy->go();
            } else {
                $this->_strategy->go();
            }
    
        }
    }
    
    /**
     * 客户端使用
     */
    $strategy = new Mine(new byBus());
    // 乘公交
    $strategy->goTravel();
    // 乘地铁
    $strategy->change(new byMetro());
    $strategy->goTravel();
    // 自驾车
    $strategy->change(new bySelfDriving());
    $strategy->goTravel();
    
    // 其他根据具体应用选择实现

    运行结果

    我乘公交出去玩
    现在改变主意,我乘地铁出去玩
    现在改变主意,我自己开着车出去玩

    7、装饰器模式

    保持接口,增强性能:修饰类继承被修饰对象的抽象父类,依赖被修饰对象的实例(被修饰对象依赖注入),以实现接口扩展

    基类传入基本的数据,可通过后面的类进行加工处理,自主组合

     8、适配器模式

    使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

     9、桥接模式

    两个维度独立变化,依赖方式实现抽象与实现分离:需要一个作为桥接的接口/抽象类,多个角度的实现类依赖注入到抽象类,使它们在抽象层建立一个关联关系

    类的组合完成业务逻辑

  • 相关阅读:
    Laravel 静态资源管理及表单布局
    Laravel 中间件的使用(前置与后置)
    Laravel 中的模板中的url
    Laravel 基础语法和include的使用
    Laravel模板的继承
    Laravel的路由、控制器和模型
    用composer安装laravel
    vue cli3.0 给路径起别名 vue.config.js ;代码统一风格 .editorconfig
    github的使用
    Java学习的第十二天
  • 原文地址:https://www.cnblogs.com/lamp01/p/8503540.html
Copyright © 2011-2022 走看看