让setter设置属于另一个类的属性的值

时间:2018-02-07 20:02:18

标签: php immutability

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;
        ...
    }    
}

我想在实例化$value之后修改Client,因为我想更改或添加一些选项。我应该在XML中使用setter并在修改请求时重新实例化Client,或者直接在Client设置一个setter,这样我就不需要重新实例化{ {1}}?

我通常更喜欢前者,但有理由认为后一种方法更受欢迎吗?除了快速更改之外,我无法想到任何事情。

1 个答案:

答案 0 :(得分:1)

通常,如果某个类具有公共方法,则应该访问它们。所以,你可能会认为使用它们没有害处。

然而,问问自己:为什么一个班级首先有吸气剂/孵化器?通常在数据对象的类上找到访问器。这些对象的主要目的是携带数据,它们通常不会任何东西 - 例如,服务或控制器类。

下一个问题:什么是构造函数?构造函数用于设置对象的内部状态,它将需要 dependencies 作为参数。本着松散耦合的精神,依赖性不应该是其他类的可变性。

查看您的代码,我想您正在编写某种基于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应该有一个工厂方法来创建这个帮助器类的实例。然后XMLClient可能有方法来使用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();
    }
}

我建议您阅读设计模式;在这种情况下,特别是关于松耦合&分离关注点,工厂方法和依赖注入。