Java设计模式之《观察者模式》及应用场景
- 思路
应该有两个角色,一个是被观察者
Observables
,一个是观察者Observer
,被观察者发生变化的时候,通知观察者,进而观察者做出自己内容的更新。是一对多的关系
<?php
//先定义一个被观察者的接口,这个接口要实现注册观察者,删除观察者和通知的功能。
interface Observables
{
public function attach(observer $ob);
public function detach(observer $ob);
public function notify();
}
// 定义一个卖家类继承这个被观察者 所有的买家都在观察卖家的价格波动
class Saler implements Observables
{
private $_observers = array(); //把观察者保存在这里
private $range = 0;
public function attach(Observer $ob)
{
$this->_observers[] = $ob;
}
public function detach(Observer $observer)
{
$key = array_search($observer,$this->observers);
if($key){
unset($this->observers[$key]);
}
}
public function notify()
{
foreach($this->_observers as $observer)
{
$observer->doActor($this);
}
}
public function price($range)
{
$this->range = $range;
}
public function getAddRange()
{
return $this->range;
}
}
//定义一个观察者的接口,这个接口要有一个在被通知的时候都要实现的方法
interface Observer
{
/**
* @param Observables $obv
* @return mixed 观察者要可以接收被观察者的类,这样才能查看被观察者的变化
*/
public function doActor(Observables $obv);
}
// 定义一个低收入观察者
class PoorBuyer implements Observer
{
//PoorBurer的做法
public function doActor(observables $obv)
{
if($obv->getAddRange() > 10)
echo '不买了.<br />';
else
echo '还行,买一点吧.<br />';
}
}
// 定义一个高收入观察者
class RichBuyer implements Observer
{
//RichBuyer的做法
public function doActor(observables $obv)
{
echo '你再涨我也不怕,咱不差钱.<br />';
}
}
$saler = new Saler(); //卖家(被观察者)
$saler->attach(new PoorBuyer()); //注册一个低收入的消费者(观察者)
$saler->attach(new RichBuyer()); //注册一个高收入的消费者(观察者)
$saler->notify(); //通知
//打印得到
//还行,买一点吧.
//你再涨我也不怕,咱不差钱.
$saler->price(15); //涨价
$saler->notify(); //通知
//不买了.
//你再涨我也不怕,咱不差钱.
-如果我们想要操作一个观察者类
$saler_new = new Saler(); //小贩(被观察者)
$saler_new->price(15); //涨价
$buy = new PoorBuyer();
$buy->doActor($saler_new);
// 不买了.
- 再看一个移除观察者的例子
$saler = new Saler(); //小贩(被观察者)
$saler->attach(new PoorBuyer()); //注册一个低收入的消费者(观察者)
$saler->attach(new RichBuyer()); //注册一个高收入的消费者(观察者)
$saler->detach(new RichBuyer());
$saler->increPrice(15); //涨价
$saler->notify(); //通知
// 得到的是 不买了
在实际应用中,其实他类似一个触发器的作用,当被观察者改变了,观察者做一些操作数据库的动作,这样就实现了消息订阅
观察者模式有两种交互模式,一种是接听 一种是推送
内置有两个SLI
我们可以直接引用\SplSubject
,\SplObserver
<?php
class Observer implements \SplObserver{
public function update(SplSubject $subject)
{
return $subject->getPrice();
}
}
class Subject implements \SplSubject{
protected $price;
protected $observers;
public function attach(SplObserver $observer)
{
$this->observers[] = $observer;
}
public function detach(SplObserver $observer)
{
$key = array_search($observer,$this->observers);
if($key){
unset($this->observers[$key]);
}
}
public function setPrice($price)
{
$this->price = $price;
if ($this->price > 12){
$this->notify();
}
return true;
}
public function getPrice()
{
return $this->price;
}
public function notify()
{
// /**
// * $observer Observer
// */
// foreach ($this->observers as $observer){
// $observer->update($this);
// }
}
}
$observer1= new Observer();
$observer2= new Observer();
$observer3= new Observer();
$subject = new Subject();
$subject->attach($observer1);
echo $observer1->update($subject);
$subject->setPrice(15);
//$subject->notify();
echo $observer1->update($subject);
echo $observer2->update($subject);
echo $observer2->update($subject);