zoukankan      html  css  js  c++  java
  • 深入 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);
        }
    }
    

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

    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. 如果想要不同的英雄拥有不同的技能,在英雄出生时选择即可。

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

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

  • 相关阅读:
    jq工具函数(八)使用$.extend()扩展工具函数
    jq工具函数(七)URL操作函数
    jq工具函数(六)字符串操作函数
    jq工具函数(四)检测对象是否为原始对象
    jq工具函数(二)检测浏览器是否属于W3C盒子模型
    jq工具类函数(一)获取浏览器的名称与版本信息
    linux
    记录---待探索
    html倒计时 照着练习(抄袭)的
    css基础
  • 原文地址:https://www.cnblogs.com/danhuang/p/13189374.html
Copyright © 2011-2022 走看看