多态性和依赖注入 - 依赖性太多

时间:2015-01-13 12:43:41

标签: php dependency-injection polymorphism

所以我读过如果我们看到一个switch语句,它就表明它需要多态性。

我看到了这样的多态性示例:

include 'vendor/autoload.php';

$calc = new Calculator();

$calc->setOperands(5, 6);
$calc->setOperation(new Addition);
echo $result = $calc->calculate();

当然可以有各种类,如Subtract,Multiply,Root等。

现在假设我想在Laravel框架中使用此代码,但我认为这应该适用于任何php框架。

添加类的示例(同样可以使用任何其他计算器函数)

Class Addition implements Operation {
    public function run($num, $current){
        return $current + $num;
    }

}

计算器:

Class Calculator {

    protected $result = 0;
    protected $operands = array();
    protected $operation;

    public function getResult()
    {
        return $this->result;
    }

    public function setOperands()
    {
        $this->operands = func_get_args();
    }

    public function setOperation(Operation $operation)
    {
        $this->operation = $operation;
    }

    public function calculate()
    {
        foreach ($this->operands as $num) {
            echo $num;
            if ( ! is_numeric($num)) {
                throw new InvalidArgumentException;
            }
            $this->result = $this->operation->run($num, $this->result);
        }

        return $this->result;
    }




}

我写了一个这样的课:

class CalcUser
{
  private $calc; 

  public function __construct(Calculator $calc)
  {
    $this->calc = $calc;
  }

  public function index()
  {
    $this->calc->setOperands(5, 6);
    $this->calc->setOperation(new Addition);
    $result = $calc->calculate();

    // imagine we have long formula to calculate so we add here many functions
    // (5+6) * 12 + 21  / 6 + sqrt(4) ...
    $this->calc->setOperands($result, 6);
    $this->calc->setOperation(new AnyOtherFunction);
    echo $result = $calc->calculate();

  }

}

这应该有效,没有测试我的CalcUser类,只是直接写在这里。

但我发现一个问题 - 使用了关键字 new

我所读到的也是:

不可测试代码的迹象:

  
      
  1. 新运营商
  2.         

    唯一可以在其中实例化类的时间   另一个类就是那个对象就是我们所说的那个   value-object,或带有getter和setter的简单容器   不做任何实际的工作。

好的,现在我可以添加Addition类,并将其他类添加到构造函数作为参数,就像我使用计算器类和 new 运算符一样。

但是还有另外一件事:

  

依赖性太多

     

如果您发现特定课程需要四个或更多   依赖性,这通常是一个告诉你的标志   上课要求太多了

因此,仅使用计算器就可以轻松获得3个以上的依赖关系,具有许多不同的功能。

那么我应该如何重新格式化代码以避免依赖太多?

1 个答案:

答案 0 :(得分:0)

在这个问题上有很多不同的观点(类何时依赖于某些东西),但类依赖性通常被视为传递给构造函数的内容,即将类实例化为对象所需的内容。因此,当您拥有计算器的实例时,调用方法并将另一个对象(在本例中为Operation的实现 - )传递给方法并不是直接依赖。

所以基本上你的Calculator类没有依赖关系,你的CalcUser有一个依赖关系(Calculator)。

另外,我认为关于new - keyword / construct的事情是,类不应该自己调用某些东西,通过那里传递方法依赖。这可能表明,如果新实例化的对象仅用于该类的生态系统中,则它是多余的。假设你从不在依赖它的类中的其他地方使用Operation,即在这种情况下:

class Calculator
{

    ...

    public function newSumOperation()
    {
        $this->setOperands(func_get_args());
        $this->setOperation(new Addition);
    }

   ...
}

class CalcUser
{
    ... 
    public function index()
    {
        $this->calc->newSumOperation(1,2,3);
        $result = $this->calc->calculate();

        // imagine we have long formula to calculate so we add here many functions
        // (5+6) * 12 + 21  / 6 + sqrt(4) ...
        $this->newXXXXXOperation(4,3,2);
        echo $result = $calc->calculate();

    }

}

因此,正如您所见,在上面的示例中,您永远不会在Addition - 类之外使用Calculator。如果你想到一个真正的计算器,你可以输入数字并得到结果;在这之间,计算器并没有将数字加在一起的逻辑推进到别的地方,因为计算器 job 做了一个补充。