设计模式之观察者模式

来源:互联网 发布:微信表白墙源码 编辑:程序博客网 时间:2024/06/11 10:20
<?php//1.有一个主题接口,提供观察者注册和通知的//2.有一堆观察者,观察者先向主题注册,然后主题通知观察者干什么//主题接口interface Subject {public function register(Observer $observer);public function notify();}//观察者接口interface Observer {public function watch();}class Action implements Subject {public $observers = array ();public function register(Observer $observer) {$this->observers [] = $observer;}public function notify() {foreach ( $this->observers as $observer ) {$observer->watch ();}}}class Cat implements Observer {public function watch() {echo 'cat watch tv';echo '<br/>';}}class Person implements Observer {public function watch() {echo 'person watch tv';echo '<br/>';}}class Dog implements Observer {public function watch() {echo 'dog watch tv';echo '<br/>';}}$action = new Action ();$action->register ( new Cat () );$action->register ( new Dog () );$action->register ( new Person () );$action->notify ();//php给出的主题接口和观察者接口 SplSubject SplObserverclass test implements SplSubject {public $observers = array ();public function attach(SplObserver $observer) {$this->observers [] = $observer;}public function detach(SplObserver $observer) {$index = array_search ( $observer, $this->observers );if ($index) {unset ( $this->observers [$index] );}}public function notify() {foreach ( $this->observers as $observer ) {$observer->update ();}}}class test2 implements SplObserver {public function update(SplSubject $subject) {echo $subject->mall;}}/** * 观察者模式应用场景实例 * * 免责声明:本文只是以哈票网举例,示例中并未涉及哈票网任何业务代码,全部原创,如有雷同,纯属巧合。 * * 场景描述: * 哈票以购票为核心业务(此模式不限于该业务),但围绕购票会产生不同的其他逻辑,如: * 1、购票后记录文本日志 * 2、购票后记录数据库日志 * 3、购票后发送短信 * 4、购票送抵扣卷、兑换卷、积分 * 5、其他各类活动等 * * 传统解决方案: * 在购票逻辑等类内部增加相关代码,完成各种逻辑。 * * 存在问题: * 1、一旦某个业务逻辑发生改变,如购票业务中增加其他业务逻辑,需要修改购票核心文件、甚至购票流程。 * 2、日积月累后,文件冗长,导致后续维护困难。 * * 存在问题原因主要是程序的"紧密耦合",使用观察模式将目前的业务逻辑优化成"松耦合",达到易维护、易修改的目的, * 同时也符合面向接口编程的思想。 * * 观察者模式典型实现方式: * 1、定义2个接口:观察者(通知)接口、被观察者(主题)接口 * 2、定义2个类,观察者对象实现观察者接口、主题类实现被观者接口 * 3、主题类注册自己需要通知的观察者 * 4、主题类某个业务逻辑发生时通知观察者对象,每个观察者执行自己的业务逻辑。 * * 示例:如以下代码 * */date_default_timezone_set ( 'PRC' ); //设置中国时区#===================定义观察者、被观察者接口============/** * * 观察者接口(通知接口) * */interface ITicketObserver //观察者接口{function onBuyTicketOver($sender, $args); //得到通知后调用的方法}/** * * 主题接口 * */interface ITicketObservable //被观察对象接口{function addObserver($observer); //提供注册观察者方法}#====================主题类实现========================/** * * 主题类(购票) * */class HipiaoBuy implements ITicketObservable { //实现主题接口(被观察者)private $_observers = array (); //通知数组(观察者)public function buyTicket($ticket) //购票核心类,处理购票流程{// TODO 购票逻辑//循环通知,调用其onBuyTicketOver实现不同业务逻辑foreach ( $this->_observers as $obs )$obs->onBuyTicketOver ( $this, $ticket ); //$this 可用来获取主题类句柄,在通知中使用}//添加通知public function addObserver($observer) //添加N个通知{$this->_observers [] = $observer;}}#=========================定义多个通知====================//短信日志通知class HipiaoMSM implements ITicketObserver {public function onBuyTicketOver($sender, $ticket) {echo (date ( 'Y-m-d H:i:s' ) . " 短信日志记录:购票成功:$ticket<br>");}}//文本日志通知class HipiaoTxt implements ITicketObserver {public function onBuyTicketOver($sender, $ticket) {echo (date ( 'Y-m-d H:i:s' ) . " 文本日志记录:购票成功:$ticket<br>");}}//抵扣卷赠送通知class HipiaoDiKou implements ITicketObserver {public function onBuyTicketOver($sender, $ticket) {echo (date ( 'Y-m-d H:i:s' ) . " 赠送抵扣卷:购票成功:$ticket 赠送10元抵扣卷1张。<br>");}}#============================用户购票====================$buy = new HipiaoBuy ();$buy->addObserver ( new HipiaoMSM () ); //根据不同业务逻辑加入各种通知$buy->addObserver ( new HipiaoTxt () );$buy->addObserver ( new HipiaoDiKou () );//购票$buy->buyTicket ( "一排一号" );/**    * 3.1php设计模式-观测者模式    * 3.1.1概念:其实观察者模式这是一种较为容易去理解的一种模式吧,它是一种事件系统,意味    *          着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,    *          观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间  *          紧密耦合的另一种方法  * 3.1.2关键点:  *        1.被观察者->追加观察者;->一处观察者;->满足条件时通知观察者;->观察条件  *        2.观察者 ->接受观察方法  * 3.1.3缺点:  * 3.1.4观察者模式在PHP中的应用场合:在web开发中观察者应用的方面很多  *        典型的:用户注册(验证邮件,用户信息激活),购物网站下单时邮件/短信通知等  * 3.1.5php内部的支持  *        SplSubject 接口,它代表着被观察的对象,  *        其结构:  *        interface SplSubject  *        {  *            public function attach(SplObserver $observer);  *            public function detach(SplObserver $observer);  *            public function notify();  *        }  *        SplObserver 接口,它代表着充当观察者的对象,  *        其结构:  *        interface SplObserver  *        {     *            public function update(SplSubject $subject);  *        }  */ /**  * 用户登陆-诠释观察者模式  */class User implements SplSubject {public $email='532252324@qq.com';public $title='测试观察者模式';public $content='观察者模式测试成功';    //注册观察者    public $observers = array();    public function __construct($data){    $this->email=$data['email'];    $this->title=$data['title'];    $this->content=$data['content'];    }    /**     * 追加观察者     * @param SplObserver $observer 观察者     * @param int $type 观察类型     */    public function attach(SplObserver $observer)    {        $this->observers[] = $observer;    }    /**     * 去除观察者     * @param SplObserver $observer 观察者     * @param int $type 观察类型     */    public function detach(SplObserver $observer)    {        if($idx = array_search($observer, $this->observers, true))        {            unset($this->observers[$idx]);        }    }    /**     * 满足条件时通知观察者     * @param int $type 观察类型     */    public function notify()    {        if(!empty($this->observers))        {            foreach($this->observers as $observer)            {                $observer->update($this);            }        }    }    /**     * 添加用户     * @param str $username 用户名     * @param str $password 密码     * @param str $email 邮箱     * @return bool     */    public function addUser()    {        //执行sql        //数据库插入成功        $res = true;        //调用通知观察者        $this->notify();        return $res;    }    /**     * 用户信息编辑     * @param str $username 用户名     * @param str $password 密码     * @param str $email 邮箱     * @return bool     */    public function editUser()    {        //执行sql        //数据库更新成功        $res = true;        //调用通知观察者        $this->notify();        return $res;    }}/*** 观察者-发送邮件*/class Send_Mail implements SplObserver {    /**     * 相应被观察者的变更信息     * @param SplSubject $subject     */    public function update(SplSubject $subject)    {        $this->sendEmail($subject->email, $subject->title, $subject->content);    }    /**     *发送邮件     *@param str $email 邮箱地址     *@param str $title 邮件标题     *@param str $content 邮件内容     */    public function sendEmail($email, $title, $content)    {        //调用邮件接口,发送邮件        echo "email:".$email.";title:".$title.";content:".$content;    }}$data=array('email'=>'xiehuanwei@126.com','title'=>'注册','content'=>'恭喜注册成功!');$user=new User($data);$user->attach(new Send_Mail());$user->addUser();

0 0
原创粉丝点击