对象是否应该始终封装其方法所处理的数据?

Should an object always encapsulate the data that its methods work on?

我正在开发 PHP class、RequestSanitize,它将处理一些原始用户输入。我可以做到的一种方法是:

class DataSanitizer implements DataSanitizerInterface {
    protected $_schema;

    public function __construct($schema){
        $this->_schema = $schema;
        // Blah blah blah
    }

    public function sanitize($data) {
        $sanitizedData = [];

        // Blah blah blah populate $sanitizedData

         ...
        return $sanitizedData;
    }
}

所以,基本上 class 只是在调用 sanitize 时提供架构。因此,它会像这样使用:

$ds = new DataSanitizer("/path/to/schema");
$sanitizedData = $ds->sanitize($_GET);

在这种情况下,我什至可以将 sanitize 设为静态成员。

另一种选择是:

class DataSanitizer implements DataSanitizerInterface {
    protected $_schema;
    protected $_sanitizedData = [];

    public function __construct($schema){
        $this->_schema = $schema;
        // Blah blah blah
    }

    public function sanitize($data) {
        // Blah blah blah

        $this->_sanitizedData = ...
        return $this;
    }

    public function data(){
        return $this->_sanitizedData;
    }
}

可以这样使用:

$ds = new DataSanitizer("/path/to/schema");
$ds->sanitize($_GET);
$sanitizedData = $ds->data();

就即时设计和未来可扩展性而言,一种设计模式是否比另一种更有意义?或者,我应该使用第三种可能更好的设计模式吗?

在我看来, 如果你使用接口class,你可以在接口定义属性和函数。因为可以从多个 class 实现接口。 如果是这样的话,方法一应该更方便。

如果你只能使用class而不是从其他接口实现,那么使用方法2会更好。

我更喜欢选项 #1。 IMO 更干净、更容易使用,选项 #2 与第一个选项相比没有任何好处或功能。

从更高层次考虑,封装用于隐藏数据和实现细节,用于完成 class 中定义的任务。在选项 #2 中,您并没有真正隐藏实现细节,您实际上是在 "encapsulation".[=10= 的幌子下要求 class 为您存储一些不必要的东西]

如果您处于多线程环境中,选项 #1 还可以更轻松地跨线程重用您的对象。这是对你用来实际进行卫生处理的东西的可重入性质做出了很多假设,但#2 本质上让你为每个线程创建卫生对象,再次存储不必要的数据或 class.