Должен ли установщик всегда устанавливать значения своих прямых свойств, а не свойств связанных объектов? Например, у меня есть что-то вроде ниже, где клиент API принимает XML:
Class XML {
private $value;
// Setter for $value exists here
...
}
Class Client {
private $xml; // XML
public function __construct(XML $xml)
{
$this->xml = $xml;
...
}
}
Я хочу $value
модифицировано после Client
создается, потому что, скажем, я хочу изменить или добавить некоторые параметры в запрос. Должен ли я использовать сеттер в XML
и восстановить экземпляр Client
при изменении запросов, или иметь установщик в Client
непосредственно, так что мне не нужно заново создавать Client
?
Я обычно предпочитаю первое, но есть ли причина, по которой последний подход предпочтительнее? Я не могу думать ни о чем, кроме того, что легче вносить быстрые изменения.
Обычно, если у класса есть публичные методы, они предназначены для доступа. Таким образом, вы можете подумать, без вреда при их использовании.
Тем не менее, спросите себя: почему класс имеет в первую очередь методы получения / установки? Средства доступа обычно находятся в классах для объектов данных. Основная цель таких объектов — нести данные, они обычно не делать что угодно — в отличие, например, от службы или класса контроллера.
Следующий вопрос: для чего нужен конструктор? Конструктор используется для установки внутреннего состояния объекта, и для этого потребуется зависимости в качестве параметров. В духе слабой связи зависимости не должны быть изменяемыми от других классов.
Глядя на ваш код, я предполагаю, что вы пишете какое-то клиентское приложение на основе XML, и вы хотите Client
класс зависеть от экземпляра XML
учебный класс.
Изменение внутреннего состояния XML
объект из Client
это плохая идея. Другие классы, зависящие от этого экземпляра, не будут знать о модификации и, возможно, получат неожиданные результаты.
Есть несколько способов решить эту проблему, в зависимости от выполняемой задачи:
1) Если вам нужно установить значение только для контекста одного вызова метода XML
, измените метод, чтобы принять $value
в качестве параметра. Но не устанавливайте его как член объекта внутри XML
!
class XML
{
public function doSomething($value)
{
…
// do whatever you need with $value,
// but do *not* do something like $this->value = $value
}
}
2) Если взаимодействие с $value
должно быть согласованным для нескольких операций, вы должны извлечь эти операции из XML
в собственный класс работника или объекта данных. XML
должен иметь метод фабрики для создания экземпляра этого вспомогательного класса. Тогда либо XML
или же Client
может иметь методы для использования работника:
class XML
{
public function createWorker($value)
{
return new XmlWorker($value, $this);
// XmlWorker might even contain a reference to the XML instance, e.g.
return new XmlWorker($value, $this);
}
public function doSomethingWithWorker(XmlWorker $worker)
{
$value = $worker->getValue();
$worker->doWork();
}
}
class Client
{
private function doSomething()
{
$worker = $this->xml->createWorker($value);
$worker->doWork();
}
}
Я бы порекомендовал прочитать Шаблоны проектирования; в этом контексте особенно о свободном сцеплении & Разделение проблем, заводские методы и внедрение зависимостей.
Других решений пока нет …