装饰模式核心内容:

  • 观察者模式又称为发布订阅模式,定义了对象间的一对多依赖关系,当一个对象状态发生改变时,其相关依赖的其他对象都能接收到通知;
  • 观察者模式的核心在于目标(Subject)和观察者(Observer)接口,目标有一个状态属性,观察者“订阅”这个目标,当目标的状态属性发生改变时,通知所有观察者。
  • 目标状态改变只需核心业务逻辑并调用通知接口,无需关心具体的观察者及其数量,降低对象之间的耦合度;

定义一个目标抽象类,提供绑定&解绑观察者的接口供客户端使用,提供通知观察者的接口供目标实现类使用:

abstract class Subject
{
protected $stateNow;
protected $observers = []; public function attach(Observer $observer)
{
echo __CLASS__ . "绑定观察者:" . $observer->getClassName() . "\n\r";
array_push($this->observers, $observer);
} public function detach(Observer $observer)
{
$pos = 0;
foreach ($this->observers as $viewer) {
if ($viewer == $observer) {
array_splice($this->observers, $pos, 1);
}
$pos++;
}
} public function notify()
{
foreach ($this->observers as $viewer) {
echo __CLASS__ . "通知观察者:" . $viewer->getClassName() . "\n\r";
$viewer->update($this);
}
}
}

定义一个目标实现类,实现状态的变更业务:

class ConcreteSubject extends Subject
{
public function setState($state)
{
echo __CLASS__ . "修改状态并调用 notify 方法\n\r";
$this->stateNow = $state;
$this->notify();
} public function getState()
{
return $this->stateNow;
}
}

定义一个观察者抽象类,规范接收通知的接口:

abstract class Observer
{
abstract public function update(Subject $subject); abstract public function getClassName();
}

定义两个观察者实现类,实现接收通知的业务逻辑:

class ConcreteObserverEmail extends Observer
{
//维护一个指向具体目标对象的引用
private $currentState; public function update(Subject $subject)
{
$this->currentState = $subject->getState();
echo $this->getClassName() . "收到了通知,内容为:" . $this->currentState . "\n\r";
} public function getClassName() {
return __CLASS__;
}
} class ConcreteObserverPhone extends Observer
{
//维护一个指向具体目标对象的引用
private $currentState; public function update(Subject $subject)
{
$this->currentState = $subject->getState();
echo $this->getClassName() . "收到了通知,内容为:" . $this->currentState . "\n\r";
} public function getClassName() {
return __CLASS__;
}
}

定义一个客户端,给目标绑定观察者,查看效果:

class Client
{
public function main()
{
$sub = new ConcreteSubject();
$obEmail = new ConcreteObserverEmail();
$obPhone = new ConcreteObserverPhone(); $sub->attach($obEmail);
$sub->attach($obPhone);
$sub->setState('开启');
}
} (new Client())->main();

输出结果:

Subject绑定观察者:ConcreteObserverEmail
Subject绑定观察者:ConcreteObserverPhone
ConcreteSubject修改状态并调用 notify 方法
Subject通知观察者:ConcreteObserverEmail
ConcreteObserverEmail收到了通知,内容为:开启
Subject通知观察者:ConcreteObserverPhone
ConcreteObserverPhone收到了通知,内容为:开启

深入 Laravel 内核之观察者模式的更多相关文章

  1. 深入 Laravel 内核之IOC容器

    升级工厂前的准备工作 无规矩不成方圆,随着越来越多的行为出现,我们需要需要定下一些规范. 为了约束每一个行为的规范,需要定义一个行为接口: interface BehaviorInterface { ...

  2. 深入 Laravel 内核之工厂模式

    英雄与行为,依赖的诞生 首先定义一个英雄,英雄具有一些行为: class Hero { protected $behavior = []; public function show() { var_d ...

  3. 深入 Laravel 内核之装饰模式

    装饰模式核心内容: 装饰模式可以在不影响组件对象的情况下,以动态.透明的方式从外部给对象添加功能: 装饰器模式的本质就是动态组合.动态是手段,组合是目的.装饰模式是通过把复杂的功能简单化.分散化,在运 ...

  4. 深入 Laravel 内核之外观模式(门面模式)

    门面模式核心内容: 客户端与子系统的通信通过外观对象进行: 外观对象封装一系列子系统的具体对应方法,对客户端只需暴露一个单一的入口方法: 客户端通过访问外观对象即可调用子系统的基础方法,无需关心子系统 ...

  5. 深入 Laravel 内核之 PHP 反射机制和依赖注入

    结论: PHP中提供了反射类来解析类的结构: 通过反射类可以获取到类的构造函数及其参数和依赖: 给构造函数的参数递归设置默认值后,即可使用这些带默认值的参数通过 newInstanceArgs 实例化 ...

  6. laravel 实现思路以及各组件原理

    laravel 内核是个IOC容器,IOC是把本来自己实例化的对象. 通过在容器里注册,通过容器来进行实例化. laravel队列用的是redis的列表来实现.

  7. Laravel 从入门到精通系列教程

    转载;https://laravelacademy.org/laravel-tutorial-5_7 适用于 Laravel 5.5.5.6.5.7 版本,本系列教程将围绕一个 LTS 版本,然后采取 ...

  8. Laravel源码解析之从入口开始

    前言 提升能力的方法并非使用更多工具,而是解刨自己所使用的工具.今天我们从Laravel启动的第一步开始讲起. 入口文件 laravel是单入口框架,所有请求必将经过index.php define( ...

  9. Laravel核心解读--Contracts契约

    Contracts Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateContractsAuthGuard 和用户提供器 ...

随机推荐

  1. mysql 执行报错:Error querying database. Cause: java.sql.SQLSyntaxErrorException:which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

    1.这个错误发生在mysql 5.7 版本及以上版本会出现的问题: mysql 5.7版本默认的sql配置是:sql_mode="ONLY_FULL_GROUP_BY",这个配置严 ...

  2. linux查询健康状态,如何直观的判断你的Linux系统是否健康

    一提到对于查看系统运行的健康状况,可能大多数朋友考虑到的就是查看进程或者打开任务管理器,但是对于应用在真实生产环境中服务器的linux系统来说,以上两种方式都不是***效的查看方式,那么今天就给大家推 ...

  3. Maven项目打包成war包并启动war包运行

    1 项目打包 1.1 右键点击所需要打包的项目,点击如图所示 Maven clean,这里 Maven 会清除掉之前对这个项目所有的打包信息. 1.2进行完 Maven clean 操作后,在ecli ...

  4. 最基础前端路由实现,事件popstate使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. 【报错记录】Could not load dynamic library 'libnvinfer.so.6'; dlerror: libnvinfer.so.6

    执行import tensorflow的时候有如下报错 (test1) a@10980:~$ python Python 3.6.13 |Anaconda, Inc.| (default, Jun 4 ...

  6. ctypes与numpy.ctypeslib的使用

    numpy ctypeslib 与 ctypes接口使用说明 作者:elfin 目录 一.numpy.ctypeslib使用说明 1.1 准备好一个C++计算文件 1.2 ctypeslib主要的五个 ...

  7. 数据类型Table.TransformColumnTypes(Power Query 之 M 语言)

    数据源: 任意数据源 目标: 设置适合的数据类型 操作过程: 选取指定列>[主页]>[数据类型]>选取 选取指定列>[转换]>[数据类型]>选取 选取指定列> ...

  8. CF1445A Array Rearrangement 题解

    Content 有 \(t\) 组询问,每组询问给定两个长度为 \(n\) 的数列 \(\{a_i\}_{i=1}^n,\{b_i\}_{i=1}^n\) 和一个整数 \(x\),求是否能够重新对两个 ...

  9. mongodb 64位操作系统下载地址

    下载地址:https://www.mongodb.org/dl/win32/x86_64

  10. JAVA地址通过百度地图API转化为经纬度

    public static Map getLngAndLat(String address) { Map map = new HashMap(); String url = "http:// ...