Итак, я прочитал, что если мы видим оператор 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, просто написал прямо здесь.
Но я вижу одну проблему — там используется ключевое слово новый
А также то, что я прочитал, это:
Признаки непроверяемого кода:
- Новые операторы
Единственный раз, когда допустимо создать экземпляр класса внутри
другой класс, когда этот объект является то, что мы называем
объект-значение или простой контейнер с геттерами и сеттерами, которые
не выполняет никакой реальной работы
Хорошо, теперь я могу добавить класс Addition и другие классы в конструктор в качестве параметра, как я сделал с классом калькулятора и новый Оператор будет избегать.
Но тогда есть еще одна вещь:
Слишком много зависимостей
Если вы обнаружите, что конкретный класс требует четыре или более
зависимости, это чаще всего признак того, что ваш
класс просит слишком много
Таким образом, легко получить более 3-х зависимостей, используя только один калькулятор с множеством различных функций.
Так как же мне переформатировать код, чтобы избежать слишком большого количества зависимостей?
Существует множество различных представлений по этому вопросу (когда класс зависит от чего-либо), но зависимости класса обычно рассматриваются как то, что передается в конструктор, то есть то, что необходимо для создания экземпляра класса как объекта. Поэтому, когда у вас есть экземпляр вашего калькулятора, вызывающий метод и передающий другой объект — в этом случае реализация 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
-учебный класс. Если вы думаете о реальном калькуляторе, вы вводите числа и получаете результат; и между этим калькулятор не продвигает логику сложения чисел во что-то еще, потому что это калькуляторы работа сделать дополнение.
Других решений пока нет …