php设计模式(2)-- 观察者模式 -- 用trait来改进的写法
程序员文章站
2022-05-03 10:34:18
...
我的设计模式系列文章
php设计模式(1)-- 观察者模式 -- spl标准写法
php设计模式(2)-- 观察者模式 -- 用trait来改进的写法
php设计模式(3)-- 责任链(职责链)模式
php设计模式(4)-- 装饰器模式
分析
我们来重新思考一下前面的代码,发现有一个不足,我仅仅是想实现观察者,如果每个想实现观察者的类,都写那么多代码,不太好。
这里我不使用继承,原因:php只允许单继承,如果为了实现观察者模式继承的话,就不能继承别的类了。
于是使用trait来解决,效果棒呆!对于前文的4个文件,修改User.php,再添加一个MySqlSubject.php,这样的话,两个观察者类,和客户端代码无需任何修改,
最终,User类的代码只有他自己的业务逻辑,无关的代码被放到通用类MySqlSubject中,代码十分清爽,且可以重用。
代码
MySplSubject.php
User.php
效果展示同前文一样:
php设计模式(1)-- 观察者模式 -- spl标准写法
php设计模式(2)-- 观察者模式 -- 用trait来改进的写法
php设计模式(3)-- 责任链(职责链)模式
php设计模式(4)-- 装饰器模式
分析
我们来重新思考一下前面的代码,发现有一个不足,我仅仅是想实现观察者,如果每个想实现观察者的类,都写那么多代码,不太好。
这里我不使用继承,原因:php只允许单继承,如果为了实现观察者模式继承的话,就不能继承别的类了。
于是使用trait来解决,效果棒呆!对于前文的4个文件,修改User.php,再添加一个MySqlSubject.php,这样的话,两个观察者类,和客户端代码无需任何修改,
最终,User类的代码只有他自己的业务逻辑,无关的代码被放到通用类MySqlSubject中,代码十分清爽,且可以重用。
代码
MySplSubject.php
<?php // 本类是可以通用的 trait MySplSubject { /** * @var SplObjectStorage */ private $observers = NULL; private function create_observers(){ if ($this->observers==null) { $this->observers = new SplObjectStorage(); } } public function attach(SplObserver $observer) { $this->create_observers(); $this->observers->attach($observer); } public function detach(SplObserver $observer) { $this->create_observers(); $this->observers->detach($observer); } public function notify() { $this->create_observers(); foreach ($this->observers as $observer) { $observer->update($this); } } }
User.php
<?php class User implements SplSubject { // 由trait来实现接口 use MySplSubject; private $email; private $username; private $mobile; private $password; public function __construct($email, $username, $mobile, $password) { $this->email = $email; $this->username = $username; $this->mobile = $mobile; $this->password = $password; } // 这是业务逻辑 public function changePassword($newPassword) { echo __METHOD__, PHP_EOL; $this->password = $newPassword; $this->notify(); } // 专门给监听器的信息,也可以省略,然后对每个字段添加get方法 public function get_observer_info(){ return [ "email" => $this->email, "mobile" => $this->mobile, "username" => $this->username, "password" =>$this->password, ]; } }
效果展示同前文一样:
User::changePassword 向 user1@domain.com 发送电子邮件成功。内容是:你好 张三你的新密码是 654321,请妥善保管 向 手机13610002000 发送短信成功。短信内容是:你好 张三你的新密码是 654321,请妥善保管