数据抽象
隐藏实现并非只是在变量之间放上一个函数层那么简单。隐藏实现关乎抽象!类并不简单地用取值器和赋值器将其变量推向外间,而是曝露抽象接口,以便用户无需了解数据的实现就能操作数据本体。
下面每段代码都表示笛卡儿平面上的一个点。其中之一曝露了其实现,而另一个则完全隐藏了其实现。
@Data
//具象的点
public class Point {
private double x;
private double y;
}
//抽象的点
public interface Point {
double getX();
double getY{);
void setCartesian{double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
抽象点隐藏了坐标的具体实现,但清晰的表达了一种数据结构,不仅如此,这些方法固定了一套存取策略:你可以单独读取 、某个坐标,但必须通过一次原子操作设定所有坐标。
数据和对象的差异
对象把数据隐藏于抽象之后,曝露操作数据的函数。数据结构曝露其数据,没有提供有意义的函数。它们是对立的。
过程式代码(使用数据结构的代码)便于在不改动既有数据结构的前提下添加新函数。面向对象代码便于在不改动既有函数的前提下添加新类。
反过来讲说过程式代码难以添加新数据结构,因为必须修改所有函数。面向对象代码难以添加新函数,因为必须修改所有类。
混杂
混杂指一半是对象,一半是数据结构。这种结构拥有执行操作的函数,也有公共变量或公共访问器及改值器。 此类混杂增加了添加新函数的难度,也增加了添加新数据结构的难度,两面不讨好。应避免创造这种结构。
得墨忒耳律
模块不应了解它所操作对象的内部情形。对象隐藏数据,曝露操作。方法不应调用由任何函数返回的对象的方法。下列代码违反了得墨忒耳律:
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
这些代码是否违反得墨忒耳律,取决于ctxt、Options和ScratchDir是对象还是数据结构。
数据传送对象(DTO)
数据传送对象(DTO)是一个只有公共变量、没有函数的类。在与数据库通信、或解析套接字传递的消息之类场景中是非常有用的结构。不要往这类数据结构中塞进业务规则方法,把这类数据结构当成对象来用。它会导致数据结构和对象的混杂体。应该把DTO当做数据结构,并创建包含业务规则、隐藏内部数据的独立对象。