我在协调单一责任原则与封装方面遇到麻烦。似乎在各个类之间划分职责需要公开大量数据。例如,考虑一些称为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
}
}
这封装了以已知格式表示数据点的责任。假设还进行了一些健全性检查,以确认
x
和y
具有良好的值(value),这是其中一项职责。class Plotter {
public function plot(DataPoint dp) {
x = dp.getX
y = dp.getY
... plot ...
}
}
绘图仪接受
DataPoint
的一个实例并对其进行绘图。这也是一个责任:绘制一个DataPoint
实例。它不需要Plotter
具有DataPoint
的内部结构的任何知识。它只需要一个已定义且稳定的接口(interface),Plotter
如何从DataPoint
获得必要的数据。哪些是 setter/getter getX
和getY
。您可以根据需要更改DataPoint
的内部结构,只要它的界面保持不变即可。 DataPoint
的职责是保存数据点,并以定义的方式授予其他代码对其数据的访问权限。如果没有办法从DataPoint
中获取数据,则它的存在将毫无用处。所以不,SRP和封装并不矛盾。您只需要明确责任是什么。