深入 Laravel 内核之工厂模式
英雄与行为,依赖的诞生
首先定义一个英雄,英雄具有一些行为:
class Hero {
protected $behavior = [];
public function show()
{
var_dump($this->behavior);
}
}
然后定义一种名为攻击行为:
class Attack {
protected $value = 0;
public function __construct($value)
{
$this->value = $value;
}
}
改造一下英雄类,让英雄在出生的时候具有攻击行为:
class Hero {
protected $behavior = [];
public function __construct()
{
array_push($this->behavior, new Attack(10));
}
public function show()
{
var_dump($this->behavior);
}
}
这样,英雄和某个具体的行为就产生了一种依赖关系。
英雄学会了越来越多的行为
随着英雄的成长,英雄学会了越来越多的行为:
class Defend {
protected $value = 0;
public function __construct($value){}
}
class Move {
protected $speed;
public function __construct($speed){}
}
class Skill1 {
protected $name = '暴击';
public function __construct(){}
}
class Skill2 {
protected $name = '眩晕';
public function __construct(){}
}
改造一下英雄类,让英雄在出生的时候具有这些行为:
class Hero {
protected $behavior = [];
public function __construct()
{
array_push($this->behavior, new Attack(10));
array_push($this->behavior, new Defend(5));
array_push($this->behavior, new Move(30));
array_push($this->behavior, new Skill1());
array_push($this->behavior, new Skill2());
}
public function show()
{
var_dump($this->behavior);
}
}
随着行为的增加,暴露出了几个问题:
- 每增加一种行为,就必须修改一次英雄类;
- 如果想让不同的英雄拥有不同的技能,需要创建很多不同的英雄类。
通过工厂模式,实现依赖转移
定义一个行为工厂,英雄出生时可以在行为工厂中挑选行为:
class BehaviorFactory
{
public function makeBehavior($behaviorName, $options=[])
{
switch ($behaviorName) {
case 'Attack': return new Attack($options[0]);
case 'Defend': return new Defend($options[0]);
case 'Move': return new Move($options[0]);
case 'Skill1': return new Skill1();
case 'Skill2': return new Skill2();
}
}
}
修改英雄类,让英雄可以去工厂中学习行为:
class Hero
{
protected $behavior = [];
public function __construct(array $behaviors)
{
// 初始化工厂
$factory = new BehaviorFactory();
// 通过工厂提供的方法制造需要的模块
foreach ($behaviors as $behaviorName => $behaviorOptions) {
$this->behavior[] = $factory->makeBehavior($behaviorName, $behaviorOptions);
}
}
}
$hero = new Hero([
'Attack' => [10],
'Defend' => [5],
'Move' => [30],
'Skill1' => [],
]);
引入工厂模式,我们解决了上述的两个问题:
- 使得英雄类不再依赖其他行为类,增加任意一种行为,都不需要修改英雄类;
- 如果想要不同的英雄拥有不同的技能,在英雄出生时选择即可。
但同时我们也引入了一个新的问题,每增加一种行为,就需要在工厂中增加一条生产线。
后面,我们将讲解如果使用一个更高级的工厂-服务容器来解决工厂模式存在的问题。
深入 Laravel 内核之工厂模式的更多相关文章
- 深入 Laravel 内核之外观模式(门面模式)
门面模式核心内容: 客户端与子系统的通信通过外观对象进行: 外观对象封装一系列子系统的具体对应方法,对客户端只需暴露一个单一的入口方法: 客户端通过访问外观对象即可调用子系统的基础方法,无需关心子系统 ...
- laravel 工厂模式到容器
下面实现了查人拥有超能力的三种方式 第一种最基本的类引用实现 1 <?php /** * 目的:代码的完善来说明从 基础类的调用到 工厂类的使用 再到容器的出现的原因 * (首先要明白工厂类和容 ...
- 23种设计模式--工厂模式-Factory Pattern
一.工厂模式的介绍 工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...
- javascript工厂模式和构造函数模式创建对象
一.工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(本书后面还将讨论其他设计模式及其在JavaScript 中的实现).考虑到在ECMAScript 中无法创 ...
- PHP设计模式(三)抽象工厂模式(Abstract Factory For PHP)
一.什么是抽象工厂模式 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足以下条件: 系统中有多个产品族,而系统一次只可能消费其中一族产品. 同 ...
- PHP设计模式(一)简单工厂模式 (Simple Factory For PHP)
最近天气变化无常,身为程序猿的寡人!~终究难耐天气的挑战,病倒了,果然,程序猿还需多保养自己的身体,有句话这么说:一生只有两件事能报复你:不够努力的辜负和过度消耗身体的后患.话不多说,开始吧. 一.什 ...
- 设计模式之工厂模式VS抽象工厂
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- 菜鸟理解的工厂模式(Factory Pattern)是什么样子的?
直接开始说了,不浪费园友宝贵的时间! 什么是工厂模式? 在学习前,先问一下:"它是什么?". 工厂模式,它是项目里面常用的设计模式之一. 它是属于创建型模式,简单的理解创建型模式就 ...
- PHP 面向对象编程和设计模式 (3/5) - 单例模式和工厂模式
PHP高级程序设计 学习笔记 2014.06.11 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容 ...
随机推荐
- 优化 if-else 代码的 8 种方案
前言 代码中如果if-else比较多,阅读起来比较困难,维护起来也比较困难,很容易出bug,接下来,本文将介绍优化if-else代码的八种方案. 方案. 优化方案一:提前return,去除不必要的el ...
- Linux基础命令---slabtop
slabtop slabtop实时显示详细的内核板条缓存信息.它显示按所列排序条件之一排序的顶级缓存的列表.它还会显示一个统计信息头,其中填充了板坯层信息. 此命令的适用范围:RedHat.RHEL. ...
- zabbix之微信报警
#:先在企业微信注册一个企业微信号 #:注册好之后,进入微信 #:测试一下 #:获取access_token #:开始获取 #:获取 #:在server端安装pip root@ubuntu:~# ap ...
- 解决“该Jenkins实例似乎已离线”
在jenkins/pluginManager/advanced最下面 把:https://updates.jenkins-ci.org/update-center.json 换成: 1.http:// ...
- python3.6.4 scrapy框架from PIL import Image报错 from . import _imaging as core
scrapy框架爬取url下载图片时,用ImagesPipeline下载图片 from PIL import Image报错 from . import _imaging as core Import ...
- Nginx编译添加新模块
目录 一.简介与思路 一.简介与思路 当前适用于nginx已经在安装过了,如果没安装过,直接在编译时候添加模块即可. Nginx主要程序就是nginx这个二进制脚本,只要在编译一个nginx脚本替换掉 ...
- 层次分析法、模糊综合评测法实例分析(涵盖各个过程讲解、原创实例示范、MATLAB源码公布)
目录 一.先定个小目标 二.层次分析法部分 2.1 思路总括 2.2 构造两两比较矩阵 2.3 权重计算方法 2.3.1 算术平均法求权重 2.3.2 几何平均法求权重 2.3.3 特征值法求权重 2 ...
- MQTT协议 - arduino ESP32 通过精灵一号 MQTT Broker 进行通讯的代码详解
前言 之前研究了一段时间的 COAP 协议结果爱智那边没有测试工具,然后 arduino 也没有找到合适的库,我懒癌发作也懒得修这库,就只能非常尴尬先暂时放一放了.不过我在 爱智APP -> 设 ...
- java 多线程 :ThreadLocal 共享变量多线程不同值方案;InheritableThreadLocal变量子线程中自定义值,孙线程可继承
ThreadLocal类的使用 变量值的共享可以使用public static变量的形式,所有的线程都是用同一个public static变量.如果想实现每一个线程都有自己的值.该变量可通过Thr ...
- 移动端适配文件(引入scss)
把此下代码放入scss文件 使用时候引入scss文件 @charset "UTF-8"; $yh:"Microsoft yahei"; @function rm ...