多态和依赖注入-太多的依赖 [英] Polymorphism and dependency injection - too many dependencies

查看:499
本文介绍了多态和依赖注入-太多的依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我读到,如果看到switch语句,则表明它需要多态.

So I have read that if we see a switch statement, its a sign that it needs polymorphism.

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

I saw such polymorphism example:

include 'vendor/autoload.php';

$calc = new Calculator();

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

当然可以有各种类,例如减法,乘法,根等.

And of course there can be various classes as Subtract, Multiply, Root, etc.

现在可以说我想在Laravel框架中使用此代码,但是我认为这应该适用于任何php框架.

Now lets say I want to use this code in a Laravel framework, but this I think should apply to any php framework.

加法类的示例(相同的方式可以使用任何其他计算器功能)

Example of addition class ( same way could work any other calculator function)

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类,只是直接在此处编写.

And this should work, did not test my CalcUser class, just wrote directly here.

但是我看到一个问题-使用了关键字 new

But I see one problem - there is used keyword new

我所读到的是:

不可测试代码的迹象

  1. 新运营商

唯一可以接受的实例化内部类的时间 另一个类是当该对象是我们称为的对象时 值对象,或者是一个简单的带有getter和setter的容器 没有任何实际的工作.

The only time when it’s acceptable to instantiate a class inside of another class is when that object is what we refer to as a value-object, or a simple container with getters and setters that doesn’t do any real work.

好吧,现在我可以添加Addition类,并将其他类作为参数添加到构造函数中,就像我对计算器类和 new 运算符所做的那样.

Ok, now I could add the Addition class, and other classes to constructor as parameter like I did with calculator class and new operator will be avoided.

但是还有另一件事:

依赖性过多

Too Many Dependencies

如果您发现某个特定班级需要四个或四个以上 依赖关系,这通常是一个表明您的 班级要求太多

If you find that a particular class requires four or more dependencies, this is, more often than not, a tell-tale sign that your class is asking for too much

因此,仅使用具有许多不同功能的计算器,就很容易以这种方式获得3个以上的依赖关系.

And so its easily to get more than 3 dependencies that way with calculator alone having many different functions.

那我应该如何重新格式化代码以避免过多的依赖关系?

So how should I reformat code to avoid having too many dependencies?

推荐答案

对此问题有很多不同的看法(当类依赖什么时),但是类依赖关系通常被视为传递给构造函数的东西,也就是说,将类实例化为一个对象需要什么.因此,当您拥有计算器的实例时,调用方法并将另一个对象(在本例中为Operation的实现)传递给方法不是直接依赖关系.

There are a bunch of different views on this matter (when does a class depend on something), but class dependencies are typically seen as what's passed into the constructor, i.e. what's needed for the class to be instantiated as an object. Therefore, when you have an instance of your calculator, calling a method and passing another object - in this case an implementation of Operation - into a method is not a direct dependency.

因此,基本上您的Calculator类没有依赖关系,您的CalcUser有一个依赖关系(Calculator).

So basically your Calculator class has no dependencies, your CalcUser has one dependency (Calculator).

此外,我认为关于new -keyword/construct的事情是,一个类不应在其自身上调用任何东西,而应在那儿传递方法依赖.这可能表明新实例化的对象仅在该类的生态系统中使用时是多余的.假设您永远不在依赖它的类中的任何其他位置使用Operation,即在这种情况下:

Also, I think the thing about the new-keyword/construct is that a class should not call something on itself, passing a method dependency through there. That could be a sign that the newly instantiated object is redundant if it's only used in that class' ecosystem. Say you never use Operation anywhere else beside in the class that depends on it, i.e. in this case:

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

    }

}

因此,如您所见,在上面的示例中,您从未在Calculator类之外使用Addition.如果您想到一个真正的计算器,则可以输入数字并得出结果.在这两者之间,计算器不会将加法运算的逻辑推加到其他东西上,因为是计算器 job 进行加法运算.

So, as you see, in the above example you never use Addition outside the Calculator-class. If you think of a real calculator, you put numbers in and get the result out; and in between that, the calculator doesn't push the logic of adding numbers together over to something else, because it's the calculators job to do an addition.

这篇关于多态和依赖注入-太多的依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆