英雄与行为,依赖的诞生

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

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. 【Linux】【Basis】文件

    refer to: https://en.wikipedia.org/wiki/POSIX refer to: https://en.wikipedia.org/wiki/Unix_file_type ...

  2. sql优化的8种方式

    1.设置索引. MySQL索引操作:给表列创建索引: 建表时创建索引: create table t(id int,name varchar(20),index idx_name (name)); 给 ...

  3. 通过 Ajax 发送 PUT、DELETE 请求的两种实现方式

    一.普通请求方法发送 PUT 请求 1. 如果不用 ajax 发送 PUT,我们可以通过设置一个隐藏域设置 _method 的值,如下: <form action="/emps&quo ...

  4. spring的注解AOP配置

    package com.hope.service.impl;import com.hope.service.IAccountService;import org.aspectj.lang.annota ...

  5. 使用IntelliJ IDEA创建简单的Spring Boot项目

    方法一: File - New -Project 创建结束后进行测试运行,修改代码如下: package com.springboot.testone; import org.springframew ...

  6. synchronized底层浅析(二)

    一张图了解锁升级流程:

  7. 【C/C++】例题 4-2 刽子手游戏/算法竞赛入门经典/函数和递归

    [题目] 猜单词游戏. 计算机想一个单词让你猜,你每次猜一个字母. 如果单词里有那个[字母],[所有该字母会显示出来]. 如果没有那个字母,算猜错一次.[最多只能猜错六次] 猜一个已经猜过的字母也算错 ...

  8. Apifox(2)快速上手apifox

    快速上手 使用场景 Apifox 是接口管理.开发.测试全流程集成工具,使用受众为整个研发技术团队,主要使用者为前端开发.后端开发和测试人员. 前端开发 接口文档管理 接口数据 Mock 接口调试 前 ...

  9. Jenkins集成jira

    目录 一.Jenkins中Jira插件安装 二.Jenkins中Jira配置 一.Jenkins中Jira插件安装 点击 Manage Jenkins-->Manage Plugins--> ...

  10. 宕机导致分区丢失恢复方案testdisk

    一.执行此预案的动机 云主机数据盘分区丢失 二.执行此预案的条件 1.确定用户在报障时间点之前有过数据盘分区存在,而在报障时间点该分区消失 2.在执行我们的恢复操作之前,确保将分区所在数据盘进行备份 ...