若转载教程,请注明出自SW-X框架官方文档1
<?php
/**
* 设计模式之观察者模式
* 使用场景 订阅信息,消息推送
* 小黄牛
*/
header("Content-type: text/html; charset=utf-8");
/**
*
* 抽象出通知者类
*/
abstract class Subject{
private $observers = array(); // 用户保存观察成员
# 添加观察成员
public function Attach($observer){
array_push($this->observers, $observer);
}
# 删除观察成员
public function Detach($observer){
foreach($this->observers as $k=>$v) {
if($v==$observer) {
unset($this->observers[$k]);
}
}
}
# 向观察成员群发消息
function Notify(){
foreach($this->observers as $v) {
$v->Update();
}
}
}
//具体通知者(Boss和Secretary)
class ConcreteSubject extends Subject{
public $subject_state; // 推送的内容
}
//抽象观察者
abstract class Observer{
public abstract function Update();
}
//具体观察者
class ConcreteObserver extends Observer{
private $name; // 观察者名称
private $observerState; // 保存通知者推送过来的内容
public $subject; // 通知者实例,作用是保证大家都在同一频道内
# 初始化成员属性
public function __construct($_sub,$_name){
$this->subject = $_sub;
$this->name = $_name;
}
# 输出推送的内容
public function Update(){
$this->observerState = $this->subject->subject_state;
echo "观察者:" .$this->name. "接受到的内容是:" .$this->observerState. "<br/>";
}
}
# 实例化一个频道
$A = new ConcreteSubject();
# 添加两个观察者 - 并加入同一频道
$zs = new ConcreteObserver($A, '张三');
$ls = new ConcreteObserver($A, '李四');
# 让两个观察者获得接受数据推送的权限
$A->Attach($zs);
$A->Attach($ls);
# 注入推送内容
$A->subject_state = "I Love You 小黄牛!";
# 推送消息
$A->Notify();
浏览器输出
观察者:张三接受到的内容是:I Love You 小黄牛!
观察者:李四接受到的内容是:I Love You 小黄牛!
观察者模式
抽象通知者角色(INotifier):定义了通知的接口规则。
具体通知者角色(Boss):实现抽象通知者的接口,接到状态改变立即向观察者下发通知。
抽象观察者角色(IObserver):定义接到通知后所做的操作(Update)接口规则。
具体观察者角色(JingDong):实现具体操作方法。
应用场景
订阅信息,消息推送
优点
1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
2、一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
3、一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。