search
Homephp教程php手册PHP设计模式之观察者模式示例介绍
PHP设计模式之观察者模式示例介绍Jun 13, 2016 am 09:39 AM
phpmainintroducearticlemodelExampleDesign Patterns

 这篇文章主要介绍了PHP设计模式之观察者模式(Observer)详细介绍和代码实例,需要的朋友可以参考下

【意图】

 

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新【GOF95】 又称为发布-订阅(Publish-Subscribe)模式、模型-视图(Model-View)模式、源-监听(Source-Listener)模式、或从属者(Dependents)模式

 

【观察者模式结构图】

 

 

 

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

 

1.抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。 抽象主题提供了增加和删除观察者对象的接口。

2.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。

3.具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。

4.具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。

 

【观察者模式的优点和缺点】

 

观察者模式的优点:

 

1.观察者和主题之间的耦合度较小;

2.支持广播通信;

 

观察者模式的缺点:

 

由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。

 

 

【观察者模式适用场景】

 

当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。

当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。

 

【观察者模式与其它模式】

 

1.中介者模式(Mediator):通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。

2.单例模式(singleton模式):ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。

 

 

【观察者模式PHP示例】

 代码如下:

 

/**

* 观察者模式

* @package design pattern

*/

 

/**

* 抽象主题角色

*/

interface Subject {

 

    /**

     * 增加一个新的观察者对象

     * @param Observer $observer

     */

    public function attach(Observer $observer);

 

    /**

     * 删除一个已注册过的观察者对象

     * @param Observer $observer

     */

    public function detach(Observer $observer);

 

    /**

     * 通知所有注册过的观察者对象

     */

    public function notifyObservers();

}

 

/**

* 具体主题角色

*/

class ConcreteSubject implements Subject {

 

    private $_observers;

 

    public function __construct() {

        $this->_observers = array();

    }

 

    /**

     * 增加一个新的观察者对象

     * @param Observer $observer

     */

    public function attach(Observer $observer) {

        return array_push($this->_observers, $observer);

    }

 

    /**

     * 删除一个已注册过的观察者对象

     * @param Observer $observer

     */

    public function detach(Observer $observer) {

        $index = array_search($observer, $this->_observers);

        if ($index === FALSE || ! array_key_exists($index, $this->_observers)) {

            return FALSE;

        }

 

        unset($this->_observers[$index]);

        return TRUE;

    }

 

    /**

     * 通知所有注册过的观察者对象

     */

    public function notifyObservers() {

        if (!is_array($this->_observers)) {

            return FALSE;

        }

 

        foreach ($this->_observers as $observer) {

            $observer->update();

        }

 

        return TRUE;

    }

 

}

 

/**

* 抽象观察者角色

*/

interface Observer {

 

    /**

     * 更新方法

     */

    public function update();

}

 

class ConcreteObserver implements Observer {

 

    /**

     * 观察者的名称

     * @var

     */

    private $_name;

 

    public function __construct($name) {

        $this->_name = $name;

    }

 

    /**

     * 更新方法

     */

    public function update() {

        echo 'Observer', $this->_name, ' has notified.
';

    }

 

}

实例化类:

$subject = new ConcreteSubject();

 

/* 添加第一个观察者 */

$observer1 = new ConcreteObserver('Martin');

$subject->attach($observer1);

 

echo '
The First notify:
';

$subject->notifyObservers();

 

/* 添加第二个观察者 */

$observer2 = new ConcreteObserver('phppan');

$subject->attach($observer2);

 

echo '
The Second notify:
';

$subject->notifyObservers();

 

/* 删除第一个观察者 */

$subject->detach($observer1);

 

echo '
The Third notify:
';

$subject->notifyObservers();

具体案例:

 

 /**  

  * 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 $observers = array();

 

    //动作类型

    CONST OBSERVER_TYPE_REGISTER = 1;//注册

    CONST OBSERVER_TYPE_EDIT = 2;//编辑

 

    /**

     * 追加观察者

     * @param SplObserver $observer 观察者

     * @param int $type 观察类型

     */

    public function attach(SplObserver $observer, $type)

    {

        $this->observers[$type][] = $observer;

    }

 

    /**

     * 去除观察者

     * @param SplObserver $observer 观察者

     * @param int $type 观察类型

     */

    public function detach(SplObserver $observer, $type)

    {

        if($idx = array_search($observer, $this->observers[$type], true))

        {

            unset($this->observers[$type][$idx]);

        }

    }

 

    /**

     * 满足条件时通知观察者

     * @param int $type 观察类型

     */

    public function notify($type)

    {

        if(!empty($this->observers[$type]))

        {

            foreach($this->observers[$type] as $observer)

            {

                $observer->update($this);

            }

        }

    }

 

    /**

     * 添加用户

     * @param str $username 用户名

     * @param str $password 密码

     * @param str $email 邮箱

     * @return bool

     */

    public function addUser()

    {

 

        //执行sql

 

        //数据库插入成功

        $res = true;

 

        //调用通知观察者

        $this->notify(self::OBSERVER_TYPE_REGISTER);

 

        return $res;

    }

 

    /**

     * 用户信息编辑

     * @param str $username 用户名

     * @param str $password 密码

     * @param str $email 邮箱

     * @return bool

     */

    public function editUser()

    {

 

        //执行sql

 

        //数据库更新成功

        $res = true;

 

        //调用通知观察者

        $this->notify(self::OBSERVER_TYPE_EDIT);

 

        return $res;

    }

}

 

/**

* 观察者-发送邮件

*/

class Send_Mail implements SplObserver

 {

    /**

     * 相应被观察者的变更信息

     * @param SplSubject $subject

     */

    public function update(SplSubject $subject)

    {

        $this->sendMail($subject->email, $title, $content);

    }

 

    /**

     *发送邮件

     *@param str $email 邮箱地址

     *@param str $title 邮件标题

     *@param str $content 邮件内容

     */

    public function sendEmail($email, $title, $content)

    {

        //调用邮件接口,发送邮件

    }

}

?>

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

方法:1、用“str_replace(" ","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\&nbsp\;||\xc2\xa0)/","其他字符",$str)”语句。

php怎么判断有没有小数点php怎么判断有没有小数点Apr 20, 2022 pm 08:12 PM

php判断有没有小数点的方法:1、使用“strpos(数字字符串,'.')”语法,如果返回小数点在字符串中第一次出现的位置,则有小数点;2、使用“strrpos(数字字符串,'.')”语句,如果返回小数点在字符串中最后一次出现的位置,则有。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么设置implode没有分隔符php怎么设置implode没有分隔符Apr 18, 2022 pm 05:39 PM

在PHP中,可以利用implode()函数的第一个参数来设置没有分隔符,该函数的第一个参数用于规定数组元素之间放置的内容,默认是空字符串,也可将第一个参数设置为空,语法为“implode(数组)”或者“implode("",数组)”。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment