原文详见:http://www.ucai.cn/blogdetail/7023?mid=1&f=12
可以在线运行查看效果哦!
<接上一篇>
4、观察者模式(Observer):
又叫发布订阅模式,当一个主体对象发生改变时,依赖它的多个观察者对象都得到通知并自动更新响应。就像报社一样,今天发布的消息只要是看这份报纸的人看到的都是同样的内容。如果发布另一份报纸,也是一样的。
好处:广播式通信,范围大,一呼百应,便于操作一个组团,“公有制”。
弊端:不能单独操作组团里的个体,不能实行按需分配。
应用场景:操作多个对象,并操作相同。
代码实现:
- <?php
- /**
- * 优才网公开课示例代码
- *
- * 观察者模式 Observer
- *
- * @author 优才网全栈工程师教研组
- * @see http://www.ucai.cn
- */
- function output($string) {
- echo $string . "\n";
- }
- //订单数据对象简单模拟,这个是实际需要被观察的对象(Subject),但是我们将其独立,然后
- //通过构造方法传入到我们模式中的Subject中,这样使具体业务更加独立
- class Order{
- //订单号
- private $id = '';
- //用户ID
- private $userId = '';
- //用户名
- private $userName = '';
- //价格
- private $price = '';
- //下单时间
- private $orderTime = '';
- //订单数据填充简单模拟,实际应用中可能会读取用户表单输入并处理
- public function __set($name, $value){
- if (isset($this->$name)){
- $this->$name = $value;
- }
- }
- //获取订单属性
- public function __get($name){
- if (isset($this->$name)){
- return $this->$name;
- }
- return "";
- }
- }
- //假设的DB类,便于测试,实际会存入真实数据库
- class FakeDB{
- public function save($data){
- return true;
- }
- }
- class Client {
- public static function test() {
- //初始化一个订单数据
- $order = new Order();
- $order->id = 1001;
- $order->userId = 9527;
- $order->userName = "God";
- $order->price = 20.0;
- $order->orderTime = time();
- //向数据库保存订单
- $db = new FakeDB();
- $result = $db->save($order);
- if ($result){
- //实际应用可能会写到日志文件中,这里直接输出
- output( "[OrderId:{$order->id}] [UseId:{$order->userId}] [Price:{$order->price}]" );
- //实际应用会调用邮件发送服务如sendmail,这里直接输出
- output( "Dear {$order->userName}: Your order {$order->id} was confirmed!" );
- //实际应用会调用邮件发送服务如sendmail,这里直接输出
- output( "Dear Manager: User {$order->userName}(ID:{$order->userId}) submitted a new order {$order->id}, please handle it ASAP!" );
- }
- }
- }
- Client::test();
- <?php
- /**
- * 优才网公开课示例代码
- *
- * 观察者模式 Observer
- *
- * @author 优才网全栈工程师教研组
- * @see http://www.ucai.cn
- */
- function output($string) {
- echo $string . "\n";
- }
- //订单数据对象简单模拟,这个是实际需要被观察的对象(Subject),但是我们将其独立,然后
- //通过构造方法传入到我们模式中的Subject中,这样使具体业务更加独立
- class Order{
- //订单号
- private $id = '';
- //用户ID
- private $userId = '';
- //用户名
- private $userName = '';
- //价格
- private $price = '';
- //下单时间
- private $orderTime = '';
- //订单数据填充简单模拟,实际应用中可能会读取用户表单输入并处理
- public function __set($name, $value){
- if (isset($this->$name)){
- $this->$name = $value;
- }
- }
- //获取订单属性
- public function __get($name){
- if (isset($this->$name)){
- return $this->$name;
- }
- return "";
- }
- }
- //被观察者, 负责维护观察者并在变化发生是通知观察者
- class OrderSubject implements SplSubject {
- private $observers;
- private $order;
- public function __construct(Order $order) {
- $this->observers = new SplObjectStorage();
- $this->order = $order;
- }
- //增加一个观察者
- 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 getOrder() {
- return $this->order;
- }
- }
- //记录业务数据日志 (ActionLogObserver),实际可能还要抽象一层以处理不同的Action(业务操作),这里省略
- class ActionLogObserver implements SplObserver{
- public function update(SplSubject $subject) {
- $order = $subject->getOrder();
- //实际应用可能会写到日志文件中,这里直接输出
- output( "[OrderId:{$order->id}] [UseId:{$order->userId}] [Price:{$order->price}]" );
- }
- }
- //给用户发送订单确认邮件 (UserMailObserver)
- class UserMailObserver implements SplObserver{
- public function update(SplSubject $subject) {
- $order = $subject->getOrder();
- //实际应用会调用邮件发送服务如sendmail,这里直接输出
- output( "Dear {$order->userName}: Your order {$order->id} was confirmed!" );
- }
- }
- //给管理人员发订单处理通知邮件 (AdminMailObserver)
- class AdminMailObserver implements SplObserver{
- public function update(SplSubject $subject) {
- $order = $subject->getOrder();
- //实际应用会调用邮件发送服务如sendmail,这里直接输出
- output( "Dear Manager: User {$order->userName}(ID:{$order->userId}) submitted a new order {$order->id}, please handle it ASAP!" );
- }
- }
- //假设的DB类,便于测试,实际会存入真实数据库
- class FakeDB{
- public function save($data){
- return true;
- }
- }
- class Client {
- public static function test() {
- //初始化一个订单数据
- $order = new Order();
- $order->id = 1001;
- $order->userId = 9527;
- $order->userName = "God";
- $order->price = 20.0;
- $order->orderTime = time();
- //绑定观察者
- $subject = new OrderSubject($order);
- $actionLogObserver = new ActionLogObserver();
- $userMailObserver = new UserMailObserver();
- $adminMailObserver = new AdminMailObserver();
- $subject->attach($actionLogObserver);
- $subject->attach($userMailObserver);
- $subject->attach($adminMailObserver);
- //向数据库保存订单
- $db = new FakeDB();
- $result = $db->save($order);
- if ($result){
- //通知观察者
- $subject->notify();
- }
- }
- }
- Client::test();
5、中介者模式(Mediator):
用中介对象封装一系列的对象交互,中介使各对象不需要显式地相互引用。类似于邮局,邮寄者和收件者不用自己跑很远路,通过邮局就可以。
好处:简化了对象之间的关系,减少子类的生成。
弊端:中介对象可能变得非常复杂,系统难以维护。
应用场景:不需要显示地建立交互。
代码实现:
- <?php
- /**
- * 优才网公开课示例代码
- *
- * 中介者模式 Mediator
- *
- * @author 优才网全栈工程师教研组
- * @see http://www.ucai.cn
- */
- function output($string) {
- echo $string . "\n";
- }
- abstract class Mediator { // 中介者角色
- abstract public function send($message,$colleague);
- }
- abstract class Colleague { // 抽象对象
- private $_mediator = null;
- public function __construct($mediator) {
- $this->_mediator = $mediator;
- }
- public function send($message) {
- $this->_mediator->send($message,$this);
- }
- abstract public function notify($message);
- }
- class ConcreteMediator extends Mediator { // 具体中介者角色
- private $_colleague1 = null;
- private $_colleague2 = null;
- public function send($message,$colleague) {
- if($colleague == $this->_colleague1) {
- $this->_colleague1->notify($message);
- } else {
- $this->_colleague2->notify($message);
- }
- }
- public function set($colleague1,$colleague2) {
- $this->_colleague1 = $colleague1;
- $this->_colleague2 = $colleague2;
- }
- }
- class Colleague1 extends Colleague { // 具体对象角色
- public function notify($message) {
- output(sprintf('Colleague-1: %s', $message));
- }
- }
- class Colleague2 extends Colleague { // 具体对象角色
- public function notify($message) {
- output(sprintf('Colleague-2: %s', $message));
- }
- }
- class Client {
- public static function test(){
- // client
- $objMediator = new ConcreteMediator();
- $objC1 = new Colleague1($objMediator);
- $objC2 = new Colleague2($objMediator);
- $objMediator->set($objC1,$objC2);
- $objC1->send("to c2 from c1");
- $objC2->send("to c1 from c2");
- }
- }
- Client::test();
6、状态模式(State) :
对象在不同状态下表现出不同的行为。就像女朋友一样,高兴了牵你的手,不高兴了遛狗。在两种状态下变现出不同的行为。
好处:避免if语句实用,方便增加新状态,封装了状态转换规则。
弊端:增加系统类和对象的数量。
应用场景:用于对象的不同功能的转换。
代码实现:
- <?php
- /**
- * 优才网公开课示例代码
- *
- * 状态模式 State
- *
- * @author 优才网全栈工程师教研组
- * @see http://www.ucai.cn
- */
- function output($string) {
- echo $string . "\n";
- }
- abstract class ILift {
- //电梯的四个状态
- const OPENING_STATE = 1; //门敞状态
- const CLOSING_STATE = 2; //门闭状态
- const RUNNING_STATE = 3; //运行状态
- const STOPPING_STATE = 4; //停止状态;
- //设置电梯的状态
- public abstract function setState($state);
- //首先电梯门开启动作
- public abstract function open();
- //电梯门有开启,那当然也就有关闭了
- public abstract function close();
- //电梯要能上能下,跑起来
- public abstract function run();
- //电梯还要能停下来
- public abstract function stop();
- }
- /**
- * 电梯的实现类
- */
- class Lift extends ILift {
- private $state;
- public function setState($state) {
- $this->state = $state;
- }
- //电梯门关闭
- public function close() {
- //电梯在什么状态下才能关闭
- switch ($this->state) {
- case ILift::OPENING_STATE: //如果是则可以关门,同时修改电梯状态
- $this->setState(ILift::CLOSING_STATE);
- break;
- case ILift::CLOSING_STATE: //如果电梯就是关门状态,则什么都不做
- //do nothing;
- return ;
- break;
- case ILift::RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做
- //do nothing;
- return ;
- break;
- case ILift::STOPPING_STATE: //如果是停止状态,本也是关闭的,什么也不做
- //do nothing;
- return ;
- break;
- }
- output('Lift colse');
- }
- //电梯门开启
- public function open() {
- //电梯在什么状态才能开启
- switch($this->state){
- case ILift::OPENING_STATE: //如果已经在门敞状态,则什么都不做
- //do nothing;
- return ;
- break;
- case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以开启
- $this->setState(ILift::OPENING_STATE);
- break;
- case ILift::RUNNING_STATE: //正在运行状态,则不能开门,什么都不做
- //do nothing;
- return ;
- break;
- case ILift::STOPPING_STATE: //停止状态,淡然要开门了
- $this->setState(ILift::OPENING_STATE);
- break;
- }
- output('Lift open');
- }
- ///电梯开始跑起来
- public function run() {
- switch($this->state){
- case ILift::OPENING_STATE: //如果已经在门敞状态,则不你能运行,什么都不做
- //do nothing;
- return ;
- break;
- case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以运行
- $this->setState(ILift::RUNNING_STATE);
- break;
- case ILift::RUNNING_STATE: //正在运行状态,则什么都不做
- //do nothing;
- return ;
- break;
- case ILift::STOPPING_STATE: //停止状态,可以运行
- $this->setState(ILift::RUNNING_STATE);
- }
- output('Lift run');
- }
- //电梯停止
- public function stop() {
- switch($this->state){
- case ILift::OPENING_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做
- //do nothing;
- return ;
- break;
- case ILift::CLOSING_STATE: //如是电梯时关闭状态,则当然可以停止了
- $this->setState(ILift::CLOSING_STATE);
- break;
- case ILift::RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了
- $this->setState(ILift::CLOSING_STATE);
- break;
- case ILift::STOPPING_STATE: //停止状态,什么都不做
- //do nothing;
- return ;
- break;
- }
- output('Lift stop');
- }
- }
- class Client {
- public static function test() {
- $lift = new Lift();
- //电梯的初始条件应该是停止状态
- $lift->setState(ILift::STOPPING_STATE);
- //首先是电梯门开启,人进去
- $lift->open();
- //然后电梯门关闭
- $lift->close();
- //再然后,电梯跑起来,向上或者向下
- $lift->run();
- //最后到达目的地,电梯挺下来
- $lift->stop();
- }
- }
- Client::test();
- <?php
- /**
- * 优才网公开课示例代码
- *
- * 状态模式 State
- *
- * @author 优才网全栈工程师教研组
- * @see http://www.ucai.cn
- */
- function output($string) {
- echo $string . "\n";
- }
- /**
- *
- * 定义一个电梯的接口
- */
- abstract class LiftState{
- //定义一个环境角色,也就是封装状态的变换引起的功能变化
- protected $_context;
- public function setContext(Context $context){
- $this->_context = $context;
- }
- //首先电梯门开启动作
- public abstract function open();
- //电梯门有开启,那当然也就有关闭了
- public abstract function close();
- //电梯要能上能下,跑起来
- public abstract function run();
- //电梯还要能停下来,停不下来那就扯淡了
- public abstract function stop();
- }
- /**
- * 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
- */
- class Context {
- //定义出所有的电梯状态
- static $openningState = null;
- static $closeingState = null;
- static $runningState = null;
- static $stoppingState = null;
- public function __construct() {
- self::$openningState = new OpenningState();
- self::$closeingState = new ClosingState();
- self::$runningState = new RunningState();
- self::$stoppingState = new StoppingState();
- }
- //定一个当前电梯状态
- private $_liftState;
- public function getLiftState() {
- return $this->_liftState;
- }
- public function setLiftState($liftState) {
- $this->_liftState = $liftState;
- //把当前的环境通知到各个实现类中
- $this->_liftState->setContext($this);
- }
- public function open(){
- $this->_liftState->open();
- }
- public function close(){
- $this->_liftState->close();
- }
- public function run(){
- $this->_liftState->run();
- }
- public function stop(){
- $this->_liftState->stop();
- }
- }
- /**
- * 在电梯门开启的状态下能做什么事情
- */
- class OpenningState extends LiftState {
- /**
- * 开启当然可以关闭了,我就想测试一下电梯门开关功能
- *
- */
- public function close() {
- //状态修改
- $this->_context->setLiftState(Context::$closeingState);
- //动作委托为CloseState来执行
- $this->_context->getLiftState()->close();
- }
- //打开电梯门
- public function open() {
- output('lift open...');
- }
- //门开着电梯就想跑,这电梯,吓死你!
- public function run() {
- //do nothing;
- }
- //开门还不停止?
- public function stop() {
- //do nothing;
- }
- }
- /**
- * 电梯门关闭以后,电梯可以做哪些事情
- */
- class ClosingState extends LiftState {
- //电梯门关闭,这是关闭状态要实现的动作
- public function close() {
- output('lift close...');
- }
- //电梯门关了再打开,逗你玩呢,那这个允许呀
- public function open() {
- $this->_context->setLiftState(Context::$openningState); //置为门敞状态
- $this->_context->getLiftState()->open();
- }
- //电梯门关了就跑,这是再正常不过了
- public function run() {
- $this->_context->setLiftState(Context::$runningState); //设置为运行状态;
- $this->_context->getLiftState()->run();
- }
- //电梯门关着,我就不按楼层
- public function stop() {
- $this->_context->setLiftState(Context::$stoppingState); //设置为停止状态;
- $this->_context->getLiftState()->stop();
- }
- }
- /**
- * 电梯在运行状态下能做哪些动作
- */
- class RunningState extends LiftState {
- //电梯门关闭?这是肯定了
- public function close() {
- //do nothing
- }
- //运行的时候开电梯门?你疯了!电梯不会给你开的
- public function open() {
- //do nothing
- }
- //这是在运行状态下要实现的方法
- public function run() {
- output('lift run...');
- }
- //这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了
- public function stop() {
- $this->_context->setLiftState(Context::$stoppingState); //环境设置为停止状态;
- $this->_context->getLiftState()->stop();
- }
- }
- /**
- * 在停止状态下能做什么事情
- */
- class StoppingState extends LiftState {
- //停止状态关门?电梯门本来就是关着的!
- public function close() {
- //do nothing;
- }
- //停止状态,开门,那是要的!
- public function open() {
- $this->_context->setLiftState(Context::$openningState);
- $this->_context->getLiftState()->open();
- }
- //停止状态再跑起来,正常的很
- public function run() {
- $this->_context->setLiftState(Context::$runningState);
- $this->_context->getLiftState()->run();
- }
- //停止状态是怎么发生的呢?当然是停止方法执行了
- public function stop() {
- output('lift stop...');
- }
- }
- /**
- * 模拟电梯的动作
- */
- class Client {
- public static function test() {
- $context = new Context();
- $context->setLiftState(new ClosingState());
- $context->open();
- $context->close();
- $context->run();
- $context->stop();
- }
- }
- Client::test();
相关推荐
3. 行为型模式:包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、访问者模式(Visitor)、命令模式(Command)、备忘录模式(Memento)、状态模式...
3. 行为型模式: - 责任链模式:避免将请求的发送者和接收者耦合在一起,使得多个对象都有可能处理请求。 - 命令模式:将请求封装为一个对象,以便使用不同的请求、队列请求、或者记录请求日志。 - 解释器模式:...
2. PHP设计模式的类型:PHP中常用的设计模式可以分为三大类,分别是创建型模式、结构型模式和行为型模式。创建型模式主要涉及对象实例化的过程,如单例模式、工厂模式、建造者模式等;结构型模式涉及如何组合类和...
14. 状态模式:允许对象在其内部状态改变时改变其行为。它将条件分支逻辑封装到独立的类中,使代码更易于理解和维护。 15. 模板方法模式:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。它使得子类可以不...
本资源包含了《PHP设计模式》一书中的实际代码示例,这些例程涵盖了多种设计模式,包括创建型、结构型和行为型模式。通过这些源码,开发者可以更直观地学习如何在实际项目中应用这些模式。 1. **创建型模式**: - ...
《PHP设计模式》是一本探讨如何在PHP编程中应用设计模式的书籍。设计模式是软件工程领域中,解决常见问题的模板或策略。本书作者是美国的Aaron Saray,内容详尽地介绍了各种设计模式,旨在帮助PHP开发者构建出更加...
**PHP设计模式详解** 在IT领域,设计模式是一种在特定情境下解决常见问题的标准方法,它们代表了软件设计中的最佳实践。PHP作为一种广泛使用的服务器端脚本语言,同样可以从设计模式中受益。《Learning PHP设计模式...
本压缩包“php设计模式代码”包含了作者亲笔编写的一些常见PHP设计模式的实现,下面将对这些设计模式进行详细的阐述。 1. **单例模式**:这种模式确保一个类只有一个实例,并提供一个全局访问点。在PHP中,单例模式...
PHP设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。 1. **创建型模式**: - 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 - 工厂模式:提供一个接口来创建对象,但让子类决定实例化...
PHP设计模式是将这些模式应用到PHP编程中的具体实现,可以帮助开发者编写更灵活、可维护和高效的代码。以下是对标题和描述中提及的一些设计模式的详细说明: 1. **解释器设计模式**:它允许我们创建一个简单的语言...
本文将深入探讨PHP中的面向对象和设计模式。 首先,我们来理解PHP的面向对象编程。在PHP 5及以上版本中,面向对象编程得到了全面支持,包括类、对象、继承、封装、多态等概念。类是对象的蓝图,定义了对象的属性...
例如,工厂模式、单例模式、观察者模式等,都是在PHP开发中经常用到的设计模式。通过理解这些模式,开发者可以写出更灵活、可扩展的代码,并且能够更好地与其他开发者协作。 再者,“框架”章节会介绍一些流行的PHP...
**PHP设计模式详解** 在软件开发中,设计模式是一种经过时间考验、被广泛接受的解决方案模板,用于解决常见的设计问题。对于PHP开发者来说,理解并掌握设计模式是提升代码质量和可维护性的关键步骤。设计模式并非...
《PHP设计模式》一书由美国作者Aaron Saray撰写,主要针对PHP开发者,详细阐述了在实际编程过程中如何运用设计模式提升代码质量和可维护性。设计模式是软件工程中的最佳实践,它们是解决常见问题的经验总结,使得...
3. 行为型模式:这类模式关注对象之间的交互和职责分配,包括责任链(Chain of Responsibility)、命令(Command)、解释器(Interpreter)、迭代器(Iterator)、备忘录(Memento)、观察者(Observer)、状态...
3. 行为型模式:如策略(Strategy)、模板方法(Template Method)、观察者(Observer)、责任链(Chain of Responsibility)、访问者(Visitor)、命令(Command)、迭代器(Iterator)、备忘录(Memento)、状态...
php设计模式 运行测试./vendor/bin/phpunit 创建型模式实例 单例模式 :check_mark_button: 工厂模式 :check_mark_button: 抽象工厂模式 :check_mark_button: 简单工厂模式 :check_mark_button: 静态工厂模式 :check_...
"php设计模式-designpatterns-php.zip"这个压缩包很可能包含了关于如何在PHP项目中应用设计模式的资料,特别是针对"designpatterns-php-master"这个文件名,我们可以推测这可能是一个关于PHP设计模式的开源项目或...
PHP设计模式可以帮助开发者构建更灵活、可扩展和易于维护的代码。设计模式并不是一种新技术,而是软件设计经验的结晶,它基于面向对象编程原则,如开闭原则(Open-Closed Principle)、里氏替换原则(Liskov ...