【观察者模式中主要角色】
1.抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。 抽象主题提供了增加和删除观察者对象的接口。
2.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。
3.具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
4.具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。
【观察者模式的优点和缺点】
观察者模式的优点:
1.观察者和主题之间的耦合度较小;
2.支持广播通信;
观察者模式的缺点:
由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。
【观察者模式适用场景】
当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。
当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。
【观察者模式与其它模式】
1.中介者模式(Mediator):通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。
2.单例模式(singleton模式):ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。
观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依 赖于它的对象都得到通知并自动刷新。它完美的将观察者对象和被观察者对象分离。可以在独立的对象(主体)中维护一个对主体感兴趣的依赖项(观察器)列表。 让所有观察器各自实现公共的 Observer 接口,以取消主体和依赖性对象之间的直接依赖关系。(反正我看不明白)
例一
用到了 spl (standard php library)
class MyObserver1 implements SplObserver {
public function update(SplSubject $subject) {
echo __CLASS__ . ' - ' . $subject->getName();
}
}
class MyObserver2 implements SplObserver {
public function update(SplSubject $subject) {
echo __CLASS__ . ' - ' . $subject->getName();
}
}
class MySubject implements SplSubject {
private $_observers;
private $_name;
public function __construct($name) {
$this->_observers = new SplObjectStorage();
$this->_name = $name;
}
public function attach(SplObserver $observer) {
$this->_observers->attach($observer);
}
public function detach(SplObserver $observer) {
$this->_observers->detach($observer);
}
public function notify() {
foreach ($this->_observers as $observer) {
$observer->update($this);
}
}
public function getName() {
return $this->_name;
}
}
$observer1 = new MyObserver1();
$observer2 = new MyObserver2();
$subject = new MySubject("test");
$subject->attach($observer1);
$subject->attach($observer2);
$subject->notify();
例二
1、观察者模式:当一个对象状态发生变化的时候,依赖他的对象会全部收到通知,并自动更新
2、场景:一个事件发生后,要执行一连串更新操作,传统的编程方式,就是在事件的代码之后直接假如处理逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件主体的代码
3、观察者模式实现了低耦合,非侵入式的通知,与更新机制
//事件产生者(被观察者)
abstract class EventGenerator
{
//保存众多观察者实例
private $observers = array();
//事件触发
public abstract function trigger();
//添加观察者
function addObserver(Observer $observer)
{
$this->observers[] = $observer;
}
//通知观察者
function notify()
{
foreach ($this->observers as $val) {
$val->update();
}
}
}
//观察者接口
interface Observer
{
function update($event_info = null);
}
//具体事件
class Event extends EventGenerator
{
//事件触发
function trigger()
{
echo "事件发生";
//通知观察者
$this->notify();
}
}
//观察者1
class Observer1 implements Observer
{
function update($event_info = null)
{
echo "观察者1接收到通知并执行更新";
}
}
//观察者2
class Observer2 implements Observer
{
function update($event_info = null)
{
echo "观察者2接收到通知并执行更新";
}
}
//客户端
class Client
{
static function Main()
{
$observer1 = new Observer1();
$observer2 = new Observer2();
$event = new Event();
$event->addObserver($observer1);
$event->addObserver($observer2);
$event->trigger();
}
}
Client::Main();
在客户端中,$event->trigger() 事件发生,导致observer1和observer2发生了变化,但是这些逻辑处理不是直接写在trigger()方法里面的,而是在observer1和observer2内部发生的,这样的话代码的维护和分工就变得有序而简单。
一般在一个事件发生触发多事件发生是一个事务处理,在这里我们可以直接在notify() 里面实现就好了:
function notify()
{
//事务开始:
foreach ($this->observers as $val) {
$res = $val->update();
if(!$res){
//事务回滚rollback
}
}
//事务提交commit
}