观察者模式---php实现

【观察者模式中主要角色】

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
}

猜你喜欢

转载自blog.csdn.net/ahaotata/article/details/83660825
今日推荐