我在协调单一责任原则与封装方面遇到麻烦。似乎在各个类之间划分职责需要公开大量数据。例如,考虑一些称为DataPoints的对象。 DataPoints除其他外,还用x和y坐标填充。我可以创建一个填充DataPoints的Generator类。现在,假设我要绘制这些数据点。显然,这是一个单独的责任,可能来自名为DataPointsPlotter的类。但是要绘制数据,我需要知道内部的x和y坐标是什么。一个类同时处理这两个问题,这没问题。 x和y是内部变量,但是create()和print()方法都可以访问它们。我可以公开x和y(也许通过getters/setters –ugh),也可以将DataPoints结构传递给Plotter类,但是它仍然需要深入了解x和y。我可以在向其发送x和y的DataPoints类中声明一个Plotter实例。但这仍然是一个风险。

在此示例中,如何在不违反封装的情况下使用绘图仪对x和y进行绘图?

最佳答案

class DataPoint {

    protected x, y

    public function construct(theX, theY) {
        x = theX
        y = theY
    }

    public function getX {
        return x
    }

    public function getY {
        return y
    }

}

这封装了以已知格式表示数据点的责任。假设还进行了一些健全性检查,以确认xy具有良好的值(value),这是其中一项职责。
class Plotter {

    public function plot(DataPoint dp) {
        x = dp.getX
        y = dp.getY

        ... plot ...
    }

}

绘图仪接受DataPoint的一个实例并对其进行绘图。这也是一个责任:绘制一个DataPoint实例。它不需要Plotter具有DataPoint的内部结构的任何知识。它只需要一个已定义且稳定的接口(interface),Plotter如何从DataPoint获得必要的数据。哪些是 setter/getter getXgetY。您可以根据需要更改DataPoint的内部结构,只要它的界面保持不变即可。 DataPoint的职责是保存数据点,并以定义的方式授予其他代码对其数据的访问权限。如果没有办法从DataPoint中获取数据,则它的存在将毫无用处。

所以不,SRP和封装并不矛盾。您只需要明确责任是什么。

10-08 11:58