Я думал о принципе единой ответственности, и я придумал этот вопрос. Допустим, класс должен быть введен другим. Лучше отправить второй класс в первый конструктор в качестве параметра или просто включить его в первый конструктор?
Чтобы объяснить мой вопрос, я написал этот маленький код. В первом коде A требует B и создает объект B в своем конструкторе.
require_once('classb.php');
class A {
protected $b;
public function __construct(){
$this->b = new B;
}
}
Во втором коде A принимает B в качестве параметра и присваивает его внутренней переменной $ b в конструкторе.
class A {
protected $b;
public function __construct(B $b){
$this->b = $b;
}
}
Я знаю, что одно преимущество — использование второго пути, если A нужно получить C также в некоторых случаях; вместо того, чтобы посылать сам класс конструктору A, интерфейс будет действовать как ссылка на класс, который необходимо сделать.
С другой стороны, если мы уверены, что внутри A будет только один класс, использование first позволяет сэкономить время и строки для инициализации B каждый раз.
Вопрос в том, что если поступить как первый путь нарушает какие-либо принципы передовой практики или имеет некоторые недостатки?
Если вы сомневаетесь, вы можете сделать
public function __construct(B $b = null){
if (isset($b)) $this->b = $b;
else $this->b = new B;
}
Это зависит от того, для чего фактически используются A и B. Если B — это просто деталь реализации, о которой пользователю класса A не нужно ничего знать, перейдите к методу 1. Если реализация когда-либо изменится (возможно, изменит класс B для класса C или даже сделает B устаревшим), пользователь класс А не должен менять свой код.
Если пользователь класса A должен знать о B (возможно, B является интерфейсом, и для него есть несколько вариантов), перейдите к методу 2.
я бы пошел со вторым способом с небольшими изменениями, конечно
вместо подсказки типа с классом используйте interface
( abInterface
например). Зачем? потому что это позволяет вам внедрить любую конкретную реализацию abInterface
программа для интерфейса не имплементация
позволяет предположить, что класс A является службой, при условии, что у вас есть класс приложения или файл index.php, который создает объект службы A; если вы разрешаете приложению передавать объект B, когда оно создает объект службы A, то вы в основном разрешаете приложению выбирать любой класс (он может передавать любую реализацию abInterface). Если вы сделаете это, ваш сервис будет открыт для расширения, но закрыт для модификации (вам не нужно изменять конструктор класса А, если вы хотите внедрить, например, class C
вместо class B
Вы также можете использовать зависимость контейнеры для инъекций для подключения всех ваших объектов, так что вам не нужно беспокоиться об управлении зависимостями я не говорю, что вам нужен контейнер DI для этого конкретного сценария но если вы хотите сделать это, вы можете сделать это, только если вы используете второй метод