[浅谈设计模式(三)] 让你一分钟读懂设计模式

碎碎念:

在此分享的是我学习中的一些理解和总结,大家一起学习和共勉,希望对大家有所帮助;在大家看了以后,觉得我理解和总结有不到位或者不对的地方希望大家在留言区指出,我会及时修改,感谢!!!

前言:

这篇文章接续上一篇文章,上一篇主要分享的是单例模式和适配器模式,如果有没有看过第二篇文章的朋友,下面有链接(浅谈设计模式(二))。该篇主要分享的设计模式是:观察者模式和策略模式。分享的每个设计模式都会通过 3 个方面(定义、举例说明、代码说明)进行讲解和说明。

正文:

观察者模式

1.定义:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,简单来说该模式相当于源 - 监听(Source-Listener)模式(即监听器)、发布 - 订阅(Publish-Subscribe)模式
2.举例说明:
大家看这个例子的时候,最好结合下面的代码说明一起更好理解.
有一个军营(即RegListener类),我们要想成为士兵(即观察者),首先需要去军营里面注册成为士兵(即RegListener下的add()方法),注册成功后我们就成为了真正的士兵(即listener1),所有的士兵要听从将军的命令进行战斗(即所有listener类要实现update()方法),这时敌军来犯,将军发布命令(即我们调用notice()方法),所有士兵收到命令后就开始战斗(即所有的listener类执行update()方法)。
这样的举例不知道大家是否能接受,思考了半天,感觉还是好尬呀!
3.代码说明:
A. 注册观察者(监听)的接口

interface Subject {
 public function add(Observer $observer);//增加一个新的观察者对象
 public function del(Observer $observer);//删除一个已注册过的观察者对象
 public function notice();// 通知所有注册过的观察者对象

B. 具体实现注册观察者类(监听事件)

/**
* 具体主题角色(实现观察者注册类)
*/
class RegListener implements Subject {
    private $listen;

    public function __construct() {
        $this->listen = array();
    }
    //增加一个新的观察者对象
    public function add(classname $class_object) {
        if(!in_array($class_object,$this->listen)){
            $this->listen[classname] = $class_object;
        }
    }
   // 删除一个已注册过的观察者对象
    public function del(classname $class_object) {
       if(isset($this->listen[classname])){
           unset($this->listen[classname]);
           return true;
       }
        return TRUE;
    }
    //通知所有注册过的观察者对象(触发观察者)
    public function notice() {
        //判断是否有注册过观察者
        if (!is_array($this->listen)) {
            return FALSE;
        }
       //触发所有观察者
        foreach ($this->listen as $classname=>$class_object) {
            $class_object->update($key,$val);  //观察者的操作(如:文章浏览+1,文章总数+1,积分+1)
        }
        return TRUE;
    }
}

C. 观察者的接口和操作方法(所有观察者调用接口,统一实现同一个名称的方法)

//观察者操作方法接口
interface ListenMethod  
{  
    function update($class_object);  //观察者方法【统一方法名】  ($class_object类实例化对象)
} 
//观察者1(文章浏览量+1)
class listener1 implements ListenMethod  
{  
    public function update(classnam $class_object)  
    {  
        $class_object-> setCount(1);  //setCount()可以重新定义成文章+1或其他文章浏览+1或其他逻辑操作  
    }  
}  
//观察者2(积分量+10)
class listener2 implements ListenMethod  
{  
    public function update(classnam $class_object)  
    {  
        $class_object-> setIntegral(10);    //setIntegral()也是我们监听成功后要执行的方法
    }  
}  

D. 观察者模式的调用

class Achieve 
{  
    public  function test()  
    {  
        $Listener = new RegListener();   //实例化观察者角色接口,用于注册观察者
        $Listener->add(new listener1());   //注册文章浏览+1观察者
        $Listener->add(new listener2());  //注册积分+1观察者  
        $Listener->notice();//触发监听和观察者方法:文章浏览量加1 积分量加10  
    }  
} 

策略模式

1.定义: 白话理解就是用相同的方法实现不同的功能
2.举例说明:
常见的排序算法有快速排序,冒泡排序,归并排序,选择排序等,它们实现的方法都是sort(),那么问题来了,我们怎么只通过sort()方法就可以调用所有的排序算法呢。这时,我们引入一个类,帮助我们实现。
3.代码说明:
A.Strategy (抽象策略接口类)

//抽象策略接口
  abstract class Strategy{
      abstract function sort();  //具体策略类要实现的方法
  }

B.ConcreteStrategy (具体策略类)

class StrategyA extends Strategy
  {
      public function sort()
      {
          echo "这个类是冒泡排序类 <br>";
      }
  }

 class  StrategyB  extends  Strategy 
 {  
     public  function  sort() 
     {  
         echo  "这个类是快速排序类 <br>";  
     } 
}

C.Context 类(如何实现策略类,即我们引入的类)

//实现具体策略类
class Context{ 
    protected $strategy; 
    //构造函数的参数是一个具体策略类的对象
    public function __construct(Strategy $strategy) 
    { 
        $this->strategy = $strategy; 
    } 
    public function request() 
    { 
        $this->strategy->sort();   //实现具体排序类方法
    }
}

D. 实现策略类

//调用StrategyA冒泡排序类
$strategyA = new StrategyA();
$context = new Context($strategyA);  
$context->request();    

//调用StrategyB快速排序类
$strategyB = new StrategyB();
$context = new Context($strategyB);  
$context->request();  

上一篇分享:【浅谈设计模式(二)】博客:[浅谈设计模式(二)] 让你一分钟读懂设计模式

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 1
AloneUtopia

在观察者模式的相关代码中好像有些问题,我不是很明白?请教一下

接口和对应方法的实现中两者的声明不一致?

file

file

还有在最后添加观察者的调用中似乎也有一点问题,声明的是1个参数为实例,传递了两个参数?第一个参数传递的是字符串?

file

4年前 评论
best辉 (楼主) 4年前
AloneUtopia (作者) 4年前
wz8081633 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!