英雄与行为,依赖的诞生

首先定义一个英雄,英雄具有一些行为:

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);
}
}

随着行为的增加,暴露出了几个问题:

  1. 每增加一种行为,就必须修改一次英雄类;
  2. 如果想让不同的英雄拥有不同的技能,需要创建很多不同的英雄类。

通过工厂模式,实现依赖转移

定义一个行为工厂,英雄出生时可以在行为工厂中挑选行为:

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' => [],
]);

引入工厂模式,我们解决了上述的两个问题:

  1. 使得英雄类不再依赖其他行为类,增加任意一种行为,都不需要修改英雄类;
  2. 如果想要不同的英雄拥有不同的技能,在英雄出生时选择即可。

但同时我们也引入了一个新的问题,每增加一种行为,就需要在工厂中增加一条生产线。

后面,我们将讲解如果使用一个更高级的工厂-服务容器来解决工厂模式存在的问题。

深入 Laravel 内核之工厂模式的更多相关文章

  1. 深入 Laravel 内核之外观模式(门面模式)

    门面模式核心内容: 客户端与子系统的通信通过外观对象进行: 外观对象封装一系列子系统的具体对应方法,对客户端只需暴露一个单一的入口方法: 客户端通过访问外观对象即可调用子系统的基础方法,无需关心子系统 ...

  2. laravel 工厂模式到容器

    下面实现了查人拥有超能力的三种方式 第一种最基本的类引用实现 1 <?php /** * 目的:代码的完善来说明从 基础类的调用到 工厂类的使用 再到容器的出现的原因 * (首先要明白工厂类和容 ...

  3. 23种设计模式--工厂模式-Factory Pattern

    一.工厂模式的介绍       工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...

  4. javascript工厂模式和构造函数模式创建对象

    一.工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(本书后面还将讨论其他设计模式及其在JavaScript 中的实现).考虑到在ECMAScript 中无法创 ...

  5. PHP设计模式(三)抽象工厂模式(Abstract Factory For PHP)

    一.什么是抽象工厂模式 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足以下条件: 系统中有多个产品族,而系统一次只可能消费其中一族产品. 同 ...

  6. PHP设计模式(一)简单工厂模式 (Simple Factory For PHP)

    最近天气变化无常,身为程序猿的寡人!~终究难耐天气的挑战,病倒了,果然,程序猿还需多保养自己的身体,有句话这么说:一生只有两件事能报复你:不够努力的辜负和过度消耗身体的后患.话不多说,开始吧. 一.什 ...

  7. 设计模式之工厂模式VS抽象工厂

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...

  8. 菜鸟理解的工厂模式(Factory Pattern)是什么样子的?

    直接开始说了,不浪费园友宝贵的时间! 什么是工厂模式? 在学习前,先问一下:"它是什么?". 工厂模式,它是项目里面常用的设计模式之一. 它是属于创建型模式,简单的理解创建型模式就 ...

  9. PHP 面向对象编程和设计模式 (3/5) - 单例模式和工厂模式

    PHP高级程序设计 学习笔记 2014.06.11 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容 ...

随机推荐

  1. 阿里云esc 安装 docker

    1. 更新 yum 到最新: yum update (用 root 用户登录,无需加 sudo,如果不是,需要加,即  yum update ) 2. 安装软件包:yum-util(提供 yum-co ...

  2. 设计模式学习笔记之看懂UML类图

    什么是UML: UML(统一建模语言)是当今软件设计的标准图标式语言.对于一个软件系统而言,UML语言具有以下的功能:可视化功能.说明功能.建造功能和建文档功能. UML都包括什么类型的图: 使用案例 ...

  3. .net 5 开发部署B/S程序。

    现在.net 6 已经出来了,visualStudio 2022也发行预览版了. 自 .net5 发布,.net core 与.net framework 已经走向统一.确实越来越好用了. 现在.ne ...

  4. java多线程5:线程间的通信

    在多线程系统中,彼此之间的通信协作非常重要,下面来聊聊线程间通信的几种方式. wait/notify 想像一个场景,A.B两个线程操作一个共享List对象,A对List进行add操作,B线程等待Lis ...

  5. Simple iPhone Keychain Access

    Simple iPhone Keychain Access Mar 29th, 2010 9:14 pm The keychain is about the only place that an iP ...

  6. 童鞋,[HttpClient发送文件] 的技术实践请查收

    1.荒腔走板 前几天有个童鞋在群里面问:怎么使用HttpClient发送文件? 之前我写了一个ABP上传文件,主要体现的是服务端,上传文件的动作是由前端小姐姐完成的, 我还真没有用HttpClient ...

  7. 【密码学】AES简单学习

    欧拉函数  公式 φ(n)=(p-1)(q-1) 小于x并且和x互质的数的个数   相关概念 因数:a*b=c 那么就称 a.b 是 c 的因数 素数:一个数如果除了1与它本身之外没有其他的因数,那么 ...

  8. sublime打开中文文件乱码以及打开文件出现.dump

    一.中文乱码 原因:中文文件由gbk编码,刚安装的sublime不支持转码 解决方法:调用ctrl+shift+p,输入:install package,回车,在稍后弹出的安装包框中搜索:Conver ...

  9. WebRTC + WebSocket 实现视频通话

    前言 WebRTC WebRTC(Web Real-Time Communication).Real-Time Communication,实时通讯. WebRTC能让web应用和站点之间选择性地分享 ...

  10. LuoguP7852 「EZEC-9」Yet Another Easy Problem 题解

    Content 给定 \(n,m\),你需要输出一个长度为 \(n\) 的排列,满足该排列进行不超过 \(m\) 次交换操作可以得到的最小的字典序最大. 数据范围:\(T\) 组数据,\(1\leqs ...