php 和设计模式 - 原型模式
发表于|更新于|设计模式
|总字数:211|阅读时长:1分钟|浏览量:
原型模式通常用于大对象的创建。因为每次 new 一个对象会造成很大开销,原型模式仅需内存拷贝即可。
比较简单,直接上🌰:
1 | interface Book |
常规情况下,我们会用 new 创建两个对象,然后分别设置各自的书名。现在用原型模式改造一下:
1 | $prototype = new eBook(); |
类保持不变,只在创建时该用 clone 即可。
文章作者: m-finder
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 M-finder!
相关推荐

2021-03-21
php 和设计模式 - 组合模式
将对象组合成树状层次结构以表示部分-整体的层次结构,使用户对单个对象和组合对象的使用具有一致性。 两个关键词,树状,部分-整体。 举个🌰: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667interface Component{ public function render();}class Composite implements Component{ protected array $composites = []; public function add(Component $component) { $this->composites[] = $component; } public function remove(Component $component) { $position = 0; foreach ($this->composites as $composite) { if ($composite === $component) { array_splice($this->composites, $position, 1); } $position++; } } public function getChildren(int $key): Component { return $this->composites[$key]; } public function render() { foreach ($this->composites as $composite) { $composite->render(); } }}class LeafA implements Component{ public function render() { echo 'leaf a render', PHP_EOL; }}class LeafB implements Component{ public function render() { echo 'leaf b render', PHP_EOL; }}$leafA = new LeafA();$leafB = new LeafB();$composite = new Composite();$composite->add($leafA);$composite->add($leafB);$composite->render();$composite->remove($leafA);$composite->render();$composite->getChildren(0)->render(); 比较适用于树形菜单、文件和文件夹管理等,感觉场景很有限啊……

2021-03-21
php 和设计模式 - 生成器模式
生成器模式也叫建造者模式,主要用于将一个复杂对象的构造与它的表示分离。该模式允许你使用相同的代码生成不同类型和形式的对象。 什么是复杂对象呢?举个🌰,人类,都有个脑袋,有个身体,又有两条胳膊腿儿,那么,我们就可以把人看作是一个复杂对象。 那么,对于生成器模式来说,我们要把人类对象的创建与它的实例表示进行分离。 class Human { public function setHead(string $head) { echo 'head:', $head, PHP_EOL; } public function setBody(string $body) { echo 'body:', $body, PHP_EOL; } public function setArms(string $leftArm, string $rightArm) { echo 'left arm:', $leftArm, ' right arm:', $rightArm, PHP_EOL; } } interface Builder { public function buildHead(); public function buildBody(); public function buildArms(); public function getResult(): Human; } class HumanBuilder implements Builder{ private Human $human; public function __construct() { $this->human = new Human(); } public function buildHead() { $this->human->setHead('ai'); } public function buildBody() { $this->human->setBody('body'); } public function buildArms() { $this->human->setArms('left', 'right'); } public function getResult(): Human { return $this->human; } } class Director{ public function builder(Builder $builder): Human { $builder->buildHead(); $builder->buildBody(); $builder->buildArms(); return $builder->getResult(); } } $director = new Director(); $human = $director->builder(new HumanBuilder()); 好了,生成器模式到此结束。

2021-03-21
php 和设计模式
场面话工作几年,复杂的业务场景,重复的 CURD 一直在消耗着我作为程序员的激情与精力,在设计模式这方面的积累从来都不够完善,出去面试时还经常会面临面试官的灵魂拷问,总觉得自己是不是就快被淘汰了。 所以,是时候下功夫整理下这方面的知识了。 开始之前,要考虑一个问题,我们为什么要学习设计模式呢? 首先从概念来讲,设计模式作为一种描述问题及其解决方案的方法,是无数的 IT 前辈在工作中总结出的 特定场景 下的 最佳解决方案,那么当我们遇到同样的场景时,就可以通过使用模式,来实现符合自己程序的解决方案,以此降低代码的耦合度,提高代码的质量,同时也方便我们后期对程序进行调整或拓展。 第二,现在大部分 PHP 程序都是依托于框架进行开发,一般情况下,我们对于框架的使用,只是局限于在一个强大的程序基础设施上添加一些小装饰。那么学习并掌握设计模式以后,我们就能够理解框架是如何解决问题,以及框架解决问题的策略,随着开发的深入,我们也能够以设计为导向,开发出自己的可复用的代码库,这对我们来说,也是一种极大的积累和提升。 第三,对于团队来说,人来人往是常态,对于从一开始就已经接手项目的成员来说,理解程序的逻辑会很轻松,但是对于新加入的成员来说,采用标准化设计模式的程序才是更容易的理解和掌握的存在,这可以使新成员更快的参与到项目的开发工作中,发挥出他作为项目成员的作用。 第四,设计模式定义了专业词汇,通过这些词汇,开发人员之间的沟通变得更加容易,可以节省很多沟通成本。 设计模式与面向对象密切相关,因此我应该不会简单的复制一堆模式来加以理解,而是从面向对象入手,逐渐向设计模式演深。 源码 目录对象 设计原则 设计模式分类 工厂模式 单例模式 生成器模式 原型模式 门面模式 适配器模式 装饰器模式 桥接模式 代理模式 组合模式 享元模式 依赖注入模式 注册模式 流接口模式 策略模式 模板方法模式 观察者模式 迭代器模式 责任链模式 命令行模式 备忘录模式 状态模式 访问者模式 中介者模式

2021-03-21
php 和设计模式 - 适配器例模式
适配器模式主要用于将一个类的接口转换为客户端所期望的另一个接口,也就是处理接口的兼容问题。 比如说数据库操作,有 mysql,sqllite,mongodb 等,缓存操作有 redis,memcache,file 等,都可以通过适配器模式将其统一成一致。 查阅资料的过程中,看到一个很生动的例子:🌰 某公司生产一批动物形玩具,可以张嘴闭嘴,实现如下: 1234567891011121314151617181920interface Toy{ public function openMouse(); public function closeMouse();}class Dog implements Toy{ public function openMouse() { echo 'dog open mouse', PHP_EOL; } public function closeMouse() { echo 'dog close mouse', PHP_EOL; }}$dog = new Dog();$dog->openMouse(); 某一天,该公司决定与另外一家公司合作,因为该公司的玩具可以遥控控制张嘴闭嘴,但是合作公司用的是 doOpenMouse 和 doCloseMouse 两个方法来控制玩具,这个时候,开发人员怎么办呢,直接在接口添加两个新方法?那岂不是违背了开闭原则,而且两组方法的功能高度重合,以后岂不是很难维护。 所以,适配器模式就可以大展身手了。 123456789101112131415161718192021222324252627282930313233343536373839404142interface RemoteControlToy{ public function doOpenMouse(); public function doCloseMouse();}class RemoteControlDog implements RemoteControlToy{ public function doOpenMouse() { echo 'remote control dog open mouse', PHP_EOL; } public function doCloseMouse() { echo 'remote control dog close mouse', PHP_EOL; }}class RemoteControllerToyAdapter implements Toy{ protected RemoteControlToy $adapter; public function __construct(RemoteControlToy $target) { $this->adapter = $target; } public function openMouse() { $this->adapter->doOpenMouse(); } public function closeMouse() { $this->adapter->doCloseMouse(); }}$adapterDog = new RemoteControllerToyAdapter(new RemoteControlDog());$adapterDog->openMouse(); 首先,我们定义并实现了遥控玩具接口,然后通过遥控玩具适配器进行接口转换,完成了接口统一。 那么像参考例子中提到的,如果这时候再来一个通过传入参数控制玩具张嘴的公司,只需要再添加一个适配器即可。

2021-03-21
php 和设计模式 - 享元模式
享元模式会尽量使相似的对象共享内存,能让你在有限的内存中载入更多对象。 当一个应用程序需要创建大量对象,并且这些对象的大多数状都可变为外部状态时,就很适合享元模式。 一如既往的举个🌰: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889interface Message{ public function send(User $user);}class AliMessage implements Message{ // 内部状态 protected Template $template; public function __construct(Template $template) { $this->template = $template; } // user 属于外部状态 public function send(User $user) { echo 'use ', $this->template->getTemplate(), ' send msg ', 'to user ', $user->getName(), ' by ali', PHP_EOL;; }}class MessageFactory{ protected array $messages = []; public function getMessage(Template $template) { $key = md5($template->getTemplate()); if (!array_key_exists($key, $this->messages)) { echo 'message create', PHP_EOL; $this->messages[$key] = new AliMessage($template); } return $this->messages[$key]; }}class Template{ protected string $template; public function setTemplate(string $template) { $this->template = $template; } public function getTemplate(): string { return $this->template; }}class User{ protected string $name; public function setName(string $name) { $this->name = $name; } public function getName(): string { return $this->name; }}$templateA = new Template();$templateA->setTemplate('template a');$templateB = new Template();$templateB->setTemplate('template b');$userA = new User();$userA->setName('wu');$userB = new User();$userB->setName('yf');$factory = new MessageFactory();$flyweightA = $factory->getMessage($templateA);$flyweightA->send($userA);$flyweightA->send($userB);$flyweightB = $factory->getMessage($templateB);$flyweightB->send($userA); 这次来点不一样的,贴张截图帮助理解: 可以看到,在享元工厂中,一共创建了两次 message,当我们重复用一个模板发送消息时,模板作为内部状态已经被缓存了,调用的时候直接取出即可,避免了重复创建造成的资源浪费。 例子虽然不太贴切,但是看完应该也能总结出,享元模式需要依赖于一个享元工厂以及一个享元角色,也就是咱们代码中的 AliMessage 类。

2021-03-21
php 和设计模式 - 装饰器模式
装饰器模式主要用于动态添加修改类的功能。 一般情况下,一个类提供了某些功能,如果要扩展或修改该类,我们可以扩展一个子类出来。但是装饰器模式可以使我们更为灵活的实现。 那么,装饰器模式相对继承灵活在哪儿呢? 举个🌰,我们有一个发送短信的类,现在要在发送短信前增加一些校验,发送短信后我们要记录 log: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374interface SendSms{ public function Send();}interface Decorator{ public function beforeSend(); public function afterSend();}class SmsDecorator implements Decorator{ public function beforeSend() { echo 'check', PHP_EOL; } public function afterSend() { echo 'log', PHP_EOL; }}class AuthSms implements SendSms{ protected $decorators = []; public function addDecorator(Decorator $decorator) { array_push($this->decorators, $decorator); } protected function beforeSend() { /** * @var Decorator $decorator */ foreach ($this->decorators as $decorator) { $decorator->beforeSend(); } } protected function afterSend() { $decorators = array_reverse($this->decorators); /** * @var Decorator $decorator */ foreach ($decorators as $decorator) { $decorator->afterSend(); } } public function Send() { $this->beforeSend(); echo 'auth sms is send', PHP_EOL; $this->afterSend(); }}$sms = new AuthSms();$sms->addDecorator(new SmsDecorator());$sms->send();