常用设计模式详解

Posted lamp01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用设计模式详解相关的知识,希望对你有一定的参考价值。

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

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、桥接模式

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

类的组合完成业务逻辑

技术分享图片

技术分享图片

 

以上是关于常用设计模式详解的主要内容,如果未能解决你的问题,请参考以下文章

Fragment使用详解

Unity常用组件参数详解

架构师内功心法,只是单纯听说过的原型模式详解

架构师内功心法,只是单纯听说过的原型模式详解

C#常用代码片段备忘

常用python日期日志获取内容循环的代码片段