深入 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)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容 ...
随机推荐
- Vector Bin Packing 华为讲座笔记
Vector bin packing:first fit / best fit / grasp 成本:性价比 (先验) 设计评价函数: evaluation function:cosine simil ...
- 【Matlab】imagesc的使用
imagesc(A) 将矩阵A中的元素数值按大小转化为不同颜色,并在坐标轴对应位置处以这种颜色染色 imagesc(x,y,A) x,y决定坐标范围 x,y应是两个二维向量,即x=[x1 x2],y= ...
- 莫烦python教程学习笔记——利用交叉验证计算模型得分、选择模型参数
# View more python learning tutorial on my Youtube and Youku channel!!! # Youtube video tutorial: ht ...
- Groovy获取Bean两种方式(奇淫技巧操作)
前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 背景: 在Java代码中当我们需要一个Bean对象,通常会使用spring中@Autowired注解,用来自动装配对象. 在Groovy ...
- [BUUCTF]REVERSE——[BJDCTF 2nd]guessgame
[BJDCTF 2nd]guessgame 附件 步骤: 例行查壳儿,64位程序,没有壳儿 64位ida载入,习惯性的检索程序里的字符串,看到了一串类似flag的字符串,拿去提交,成功 BJD{S1m ...
- 用 shell 脚本做自动化测试
前言 项目中有一个功能,需要监控本地文件系统的变更,例如文件的增.删.改名.文件数据变动等等.之前只在 windows 上有实现,采用的是 iocp + ReadDirectoryChanges 方案 ...
- CF615A Bulbs 题解
Content 有 \(n\) 个灯,一开始它们都是关着的.有 \(m\) 个按钮,每个按钮可以开 \(k\) 盏灯.求能否通过这 \(m\) 个按钮使得所有灯全部都开着. 数据范围:\(1\leqs ...
- Linux httpd搭建
Linux 搭建网站 配置网络 1 改对应配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens32 2 使用命令 nmcli connection add ...
- 在react项目中使用require引入图片不生效
如果使用create-react-app和require导入图像,require返回一个ES模块而不是字符串.这是因为在file-loader中,esModule选项是默认启用的. 用以下方式之一导入 ...
- Windows10 c++获取网卡信息(ipv4,子网掩码,网关,mac地址)
关于 本文样式环境: win10 + vs2017 + c++11 1.说明 算是踩坑吧,先前一直认为一块网卡只能有一个IP. 今天发现结构体中,定义了相关结构: 一块网卡可以用多个IP. 2.连接库 ...