让 setter 设置属于另一个 class 的 属性 的值
Letting a setter set a value of a property belonging to another class
setter 是否应该始终设置其直接属性的值,而不是关联对象的属性的值?例如,我有类似下面的内容,其中 API 客户端接收 XML:
Class XML {
private $value;
// Setter for $value exists here
...
}
Class Client {
private $xml; // XML
public function __construct(XML $xml)
{
$this->xml = $xml;
...
}
}
我想在实例化 Client
之后修改 $value
,因为,比方说,我想更改请求或向请求添加一些选项。我应该在 XML
中使用 setter 并在修改请求时重新实例化 Client
,还是直接在 Client
中使用 setter 这样我就不会需要重新实例化Client
?
我通常更喜欢前者,但为什么会更喜欢后一种方法?除了更容易进行快速更改之外,我想不出任何其他方法。
一般来说,如果 class 有 public 方法,就意味着可以访问它们。所以,使用它们没有坏处,你可能会想。
但是,问问自己:为什么 class 首先有 getters/setters?通常可以在 classes 上找到数据对象的访问器。这些对象的主要目的是携带数据,它们通常不会 做 任何事情——不像服务或控制器 class.
下一个问题:构造函数有什么用?构造函数用于设置对象的内部状态,它需要它的 dependencies 作为参数。本着松散耦合的精神,依赖项不应与其他 classes 可变。
查看您的代码,我猜您正在编写某种基于 XML 的客户端应用程序并且您希望 Client
class 依赖于XML
class.
从 Client
修改 XML
对象的内部状态是一个 坏主意 。依赖于该实例的其他 classes 将不知道修改并可能会得到意外结果。
有几种方法可以解决这个问题,具体取决于要执行的实际任务:
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
提取到自己的工作程序或数据对象 class 中。 XML
然后应该有一个工厂方法来创建这个助手 class 的实例。然后 XML
或 Client
可能有使用 worker 的方法:
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();
}
}
我建议阅读 设计模式;在这种情况下,尤其是关于松散耦合和关注点分离、工厂方法和依赖注入。
setter 是否应该始终设置其直接属性的值,而不是关联对象的属性的值?例如,我有类似下面的内容,其中 API 客户端接收 XML:
Class XML {
private $value;
// Setter for $value exists here
...
}
Class Client {
private $xml; // XML
public function __construct(XML $xml)
{
$this->xml = $xml;
...
}
}
我想在实例化 Client
之后修改 $value
,因为,比方说,我想更改请求或向请求添加一些选项。我应该在 XML
中使用 setter 并在修改请求时重新实例化 Client
,还是直接在 Client
中使用 setter 这样我就不会需要重新实例化Client
?
我通常更喜欢前者,但为什么会更喜欢后一种方法?除了更容易进行快速更改之外,我想不出任何其他方法。
一般来说,如果 class 有 public 方法,就意味着可以访问它们。所以,使用它们没有坏处,你可能会想。
但是,问问自己:为什么 class 首先有 getters/setters?通常可以在 classes 上找到数据对象的访问器。这些对象的主要目的是携带数据,它们通常不会 做 任何事情——不像服务或控制器 class.
下一个问题:构造函数有什么用?构造函数用于设置对象的内部状态,它需要它的 dependencies 作为参数。本着松散耦合的精神,依赖项不应与其他 classes 可变。
查看您的代码,我猜您正在编写某种基于 XML 的客户端应用程序并且您希望 Client
class 依赖于XML
class.
从 Client
修改 XML
对象的内部状态是一个 坏主意 。依赖于该实例的其他 classes 将不知道修改并可能会得到意外结果。
有几种方法可以解决这个问题,具体取决于要执行的实际任务:
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
提取到自己的工作程序或数据对象 class 中。 XML
然后应该有一个工厂方法来创建这个助手 class 的实例。然后 XML
或 Client
可能有使用 worker 的方法:
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();
}
}
我建议阅读 设计模式;在这种情况下,尤其是关于松散耦合和关注点分离、工厂方法和依赖注入。