迭代器模式

概念 迭代器模式是遍历集合的成熟模式,迭代器模式的关键是将遍历集合的任务交给一个叫做迭代器的对象,它的工作是遍历并选择序列中的对象,而客户端程序员不必知道或关心该集合序列底层的结构。 说明 迭代器模式(Iterator),又叫做游标(Cursor)模式,提供一种方法访问一个容器(Container)对象中各个元素,而又不需要暴露该对象的内部细节。 当你需要访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。另外,当需要对聚集有多种方式遍历时,可以考虑去使用迭代器模式。迭代器模式为遍历不同的聚合结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。 作用 我们想要像遍历数组那样,遍历对象,或是遍历一个容器。 迭代器模式可以隐藏遍历元素所需的操作 应用场景 访问一个聚合对象的内容而无需暴露它的内部表示 支持对聚合对象的多种遍历 为遍历不同的聚合结构提供一个统一的接口。 角色 Iterator(迭代器):迭代器定义访问和遍历元素的接口 ConcreteIterator(具体迭代器):具体迭代器实现迭代接口,对该聚合遍历时跟踪当前位置 Aggregate(聚合):聚合定义创建相应迭代器对象的接口。 ConcreteAggregate(具体聚合):具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。 <?php //自定义迭代器实现系统定义迭代器接口 class MyIterator implements Iterator { protected $data = []; protected $index; public function __construct($data) { $this->data = $data; $this->index = 0; } //返回第一个元素 public function rewind() { $this->index = 0; } //下一个元素 public function next() { $this->index++; } //验证是否继续 public function valid() { return $this->index < count($this->data); } //返回key值 public function key() { return $this->index; } //返回当前元素 public function current() { return $this->data[$this->index]; } } $arr = [1, 2, 3, 4, 5, 6]; $iterate = new MyIterator($arr); foreach ($iterate as $dynasty) { echo 'the obj == ' ....

March 26, 2022 · 1 min · ZhaoGuibin

命令模式

概念 将一个请求封装(命令的封装)为一个对象,从而使用你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分隔开,委派给不同的对象。 请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。 角色 命令(command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。 具体命令(ConcreteCommand)角色:定义一个接收者和行为之间的弱耦合;实现Execute()方法,负责调用接收到的相应操作。Execute()方法通常叫做执行方法。 客户(client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。 优点和缺点 优点: 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分离开。 命令类与其他任何别的类一样,可以修改和推广。 可以把命令对象聚合在一起,合成为合成命令。 可以很容易的加入新的命令类。 缺点: 可能会导致某些系统有过多的具体命令类。 应用场景 抽象出待执行的动作以参数化对象。Command模式是回调机制的一个面向对象的替代品。 在不同的时刻指定、排列和执行请求。 支持取消操作 支持修改日志 用构建在原语操作上的高层操作构建一个系统。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。 <?php //抽象命令接口 interface Command { //命令执行 public function execute(); } //宏命令(命令的组合) //宏命令接口 interface MacroCommand extends Command { //宏命令聚集管理方法,可以删除一个命令 public function remove(Command $command); //宏命令聚集管理方法,可以添加一个命令 public function add(Command $command); } //命令的实现 //复制命令 class CopyCommand implements Command { private $receiver; public function __construct(Receiver $receiver) { $this->receiver = $receiver; } public function execute() { $this->receiver->copy(); } } //粘贴命令 class PasteCommand implements Command { private $receiver; public function __construct(Receiver $receiver) { $this->receiver = $receiver; } public function execute() { $this->receiver->paste(); } } //命令接收者执行命令 class Receiver { private $name; public function __construct($name) { $this->name = $name; } public function copy() { echo $this->name ....

March 26, 2022 · 2 min · ZhaoGuibin

观察者模式

概念 观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。 当一个对象状态发生改变后,会影响到其他几个对象的改变,这时候可以用观察者模式。 观察者模式符合接口隔离原则,实现了对象之间的松散耦合。 角色 抽象主题(subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。 具体主题(ConcreteSubjest):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。 <?php //抽象主题 interface Subject { //新增观察者 public function attach(Observer $observer); //移除观察者 public function detach(Observer $observer); //通知观察者 public function notifyObserver(); } //具体主题 class ConcreteSubjest implements Subject { //储存观察者 private $observers; public function __construct() { $this->observers = []; } //新增观察者 public function attach(Observer $observer) { return array_push($this->observers, $observer); } //移除观察者 public function detach(Observer $observer) { //检查观察者是否存在观察者数组中,返回索引值 $index = array_search($observer, $this->observers); if ($index === false) { return false; } else { unset($this->observers[$index]); return true; } } //通知观察者 public function notifyObserver() { if (!...

March 26, 2022 · 1 min · ZhaoGuibin

策略模式

概念 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,并让它们可以相互替换,这种模式就是策略模式。 简单理解就是 有n个做法供你选择,根据你的需要选择某个策略得到结果 优点 使用设计模式之后,我们的代码冗余和耦合度变低,每个策略模块完成对应的功能。 当然缺点就是一个功能我们就要响应制作一个策略类,但是我们统观MVC架构当中(Thinkphp,Yii2),一个控制器对应一个视图,其实也是策略模式的体现了。 <?php interface UserInterface { public function showAd(); public function showCategory(); } //男性用户实现接口 class MaleUser implements UserInterface { public function showAd() { echo '电子产品'; } public function showCategory() { echo "PS5,PC,Switch"; } } //女性用户实现接口 class FemaleUser implements UserInterface { public function showAd() { echo '化妆品'; } public function showCategory() { echo "口红,面膜"; } } //客户端实现,根据性别不同推荐不同内容 $sex = 'male'; if ($sex == 'male') { $user = new MaleUser(); } else { $user = new FemaleUser(); } $user->showAd(); $user->showCategory();

March 26, 2022 · 1 min · ZhaoGuibin

装饰器模式

概念 装饰器模式又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 实例 组件对象的接口:可以给这些对象动态的添加职责 所有装饰器的父类:需要定义一个与组件接口一直的接口,并持有一个component对象,该对象其实就是被装饰的对象。 具体的装饰器类:实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象。 使用场景 需要动态的给一个对象添加功能,这些功能可以再动态的撤销 需要添加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 <?php //组件对象接口 interface IComponent { //动态给对象添加功能 public function display(); } //待装饰的对象 class Person implements IComponent { protected $name; public function __construct($name) { $this->name = $name; } public function display() { echo '装饰的' . $this->name; } } //所有装饰器的父类 class Clothes implements IComponent { protected $component; public function Decorate(IComponent $component) { $this->component = $component; } public function display() { if (!empty($this->component)) { $this->component->display(); } } } //具体的装饰器 class Pixie extends Clothes { public function display() { echo '皮鞋'; parent::display(); } } class Waitao extends Clothes { public function display() { echo '外套'; parent::display(); } } //客户端 $gd = new Person('狗蛋'); $px = new Pixie(); $px->Decorate($gd); $px->display(); $wt = new Waitao(); $wt->Decorate($gd); $wt->display();

March 24, 2022 · 1 min · ZhaoGuibin

注册树模式

概念 注册树模式也叫注册模式或注册器模式,顾名思义,注册树就是把对象实例注册到一棵全局的对象树上,需要对象的时候就从树上取下来,就好比树上长的果子,需要的时候就摘一个下来,只是这个对象树果子是摘不完的。 作用 不管是单例模式还是工厂模式建立的对象,都没有得到很好的管理,用了注册树模式,就可以把创建出来的对象注册到全局树上,需要的时候取下来用,可以很好的管理创建的对象。 <?php class DbMysql { public function conn() { echo 'mysql conn'; } } class DbSqlite { public function conn() { echo 'sqlite conn'; } } class MysqlFactory { public static function getIns() { return new DbMysql(); } } class SqliteFactory { public static function getIns() { return new DbSqlite(); } } //注册树实现存储对象(IOC控制反转思想) class RegisterTree { protected static $objects; //添加对象到注册树中 public static function set($alias, $object) { self::$objects[$alias] = $object; } //从注册树中获取对象 public static function get($alias) { return self::$objects[$alias]; } //销毁注册树上的对象 public static function _unset($alias) { unset(self::$objects[$alias]); } } //注册 RegisterTree::set('mysql', MysqlFactory::getIns()); RegisterTree::set('sqlite', SqliteFactory::getIns()); //客户端 // $mysql = RegisterTree::get('mysql'); // $mysql->conn(); // $sqlite = RegisterTree::get('sqlite'); // $sqlite->conn(); class Facade { public static $mysql; public static $sqlite; public function __construct() { self::$mysql = RegisterTree::get('mysql'); self::$sqlite = RegisterTree::get('sqlite'); } } new Facade(); Facade::$mysql->conn(); Facade::$sqlite->conn();

March 24, 2022 · 1 min · ZhaoGuibin

门面模式

概念 门面模式(facade)又称外观模式,用于为子系统中的一组接口提供一个一致的界面。门面模式定义了一个高层接口,这个接口使得子系统更加容易使用;引入门面角色之后,用户只需要直接与门面角色交互,用户与子系统之间的复杂关系由门面角色来实现,从而降低了系统的耦合度。 作用 为一些复杂的子系统提供一组接口。 提高子系统的独立性 在层次化结构中,可以使用门面模式定义系统的每一层的接口 优点 它对于客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。 实现了子系统与客户之间的松耦合关系。 如果应用需要,它并不限制它们使用子系统类。因此可以在系统易用性与能用性之间加以选择。 <?php class Camera { public function turnOn() { echo 'turn on camera'; } public function turnOff() { echo 'turn off camera'; } } class Light { public function turnOn() { echo 'turn on light'; } public function turnOff() { echo 'turn off light'; } } //门面类 class Facade { private $camera; private $light; public function __construct() { $this->camera = new Camera(); $this->light = new Light(); } //启动接口 public function activate() { $this->camera->turnOn(); $this->light->turnOn(); } //关闭接口 public function deactivate() { $this->camera->turnOff(); $this->light->turnOff(); } } //客户端 class Client { private static $securit; public static function main() { self::$securit = new Facade(); self::$securit->activate(); self::$securit->deactivate(); } } Client::main();

March 24, 2022 · 1 min · ZhaoGuibin

管道模式

概念 管道(pipeline)设计模式流水线模式就是将数据传递到一个任务序列中,管道扮演着流水线的角色,数据在这里被处理然后传递到下一个步骤 释义 管道,顾名思义,就是一个长长的流水管道,只不过加了许多阀门。所以管道模式大致需要三个角色:管道、阀门、载荷(流水)。 目的是在管道中对载荷进行一系列的处理。因为可以对过滤器进行动态的添加,所以对载荷的处理可以变得更加灵活。但同时带来的问题是,在过滤器过多时,很难把握整体的处理逻辑。而且在某一个过滤器对载荷处理后,因为载荷改变,会造成下一个过滤器中的逻辑出错。 <?php //管道接口 interface PipelineBuilder { public function __construct($payload); //$payload载荷 public function pipe(StageBuilder $stage); //管道与阀门 public function process(); //过程 } //实现管道接口 class Pipeline implements PipelineBuilder { protected $payload; protected $pipes = []; public function __construct($payload) { $this->payload = $payload; } public function pipe(StageBuilder $stage) { $this->pipes[] = $stage; return $this; } public function process() { foreach ($this->pipes as $pipe) { call_user_func([$pipe, 'handle'], $this->payload); } } } //阀门类 interface StageBuilder { public function handle($payload); } //实现 class StageOneBuilder implements StageBuilder { public function handle($payload) { echo 'one-'; } } class StageTwoBuilder implements StageBuilder { public function handle($payload) { echo 'two-'; } } //客户端使用 $pipeline = new PipeLine('step'); $pipeline->pipe(new StageOneBuilder())->pipe(new StageTwoBuilder())->process();

March 24, 2022 · 1 min · ZhaoGuibin

代理模式

概念 构建了透明置于两个不同对象之内的一个对象,从而能够截取或代理这两个对象间的通信或访问。 应用场景 远程代理:也就是为了一个对象在不同地址空间提供局部代表。隐藏一个对象存在于不同地址空间的事实。 虚拟代理:根据需求来创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。 安全代理:用来控制真实对象的访问对象。 智能指引:当调用真实对象的时候,代理处理一些事情。 <?php //真实类 interface Subject { public function request(); } class RealSubject implements Subject { public function request() { echo '真实的操作'; } } //代理模式代理真实类 class Proxy implements Subject { protected $realSubject; public function __construct() { $this->realSubject = new RealSubject(); } public function request() { echo '代理操作'; $this->realSubject->request(); } } //客户端 $proxy = new Proxy(); $proxy->request(); 注意事项 代理模式的实现其实非常简单,或许你在不经意间经常会用到 请注意代理模式与装饰器、适配器的区别 装饰器:一般是对对象进行装饰,其中的方法行为会有增加,以修饰对象为主 适配器:一般会改变方法行为,目的是保持接口的统一但得到不同的实现 代理模式有几种形式:远程代理(例如:第三方接口SDK)、虚代理(例如:异步加载图片)、保护代理&智能指引(例如:权限保护),而我们代码实现的最普通的代理,其实就是让代理类来代替真实类的操作

March 24, 2022 · 1 min · ZhaoGuibin

适配器模式

概念 将某个类的接口转换成与另一个接口兼容。适配器通过将原始接口进行转换,给用户提供一个兼容接口,使得原来因为接口不同而无法一起使用的类可以得到兼容。 应用场景 老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。 <?php interface Weather { public function show(); } class PhpWeather implements Weather { public function show() { $weatherInfo = ['weather' => '雨', 'tep' => 6, 'wind' => 3]; return serialize($weatherInfo); } } //兼容模式 使得java能够直接使用 interface WeatherA { public function getWeather(); } class JavaWeather implements WeatherA { protected $weather; public function __construct(Weather $weather) { $this->weather = $weather; } public function getWeather() { $info = unserialize($this->weather->show()); return json_encode($info); } } $weather = new PhpWeather(); // $info = unserialize($weather); // var_dump($info); $java_weather = new JavaWeather($weather); $info = json_decode($java_weather->getWeather()); var_dump($info);

March 23, 2022 · 1 min · ZhaoGuibin