一、数据、对象的反对称性
对象:将数据隐藏于抽象之后,暴露操作数据的函数。
数据结构:暴露数据本身,不提供有意义的函数。
例如下面:
public class Point {
public double x;
public double y;
}
public interface Point {
double getX();
double getY();
void setCartsian(double x,double y);
double getR();
double getTheta();
void setPolar(double r,double theta);
}
一个暴露了实现,一个完全隐藏了实现。但是该接口还是呈现了一种数据结构。隐藏实现并非只是在变量之上加一层函数层。隐藏实现关乎抽象!类并不是简单用存储器和赋值器,而是暴露抽象接口吗,让用户无须了解数据的实现就能操作数据<b>本体</b>。
public interface Vehicle {
double getFuelTankCapacityInGallons();
double getGallonsOfGasoline();
}
public interface Vehicle {
double getPercentFuelRemaining();
}
以上两段代码以后者为佳。我们不愿暴露数据细节,更愿意以抽象的形态表述数据。<b>不要乱加取值器和赋值器,那是最坏的选择。</b>
<b>过程式(使用数据结构的代码)便于在不改动既有数据结构的前提下添加新函数。面向对象代码便于在不改动既有函数的前提下添加新类。</b>
反过来讲也说得通:
<b>过程是代码难以添加新的数据结构,因为必须修改所有函数;面向对象代码难以添加新函数,因为必须修改所有类。</b>
结论:一切对象都是传说,有时候必须做一些过程式的操作。
二、得墨忒耳律
The Law of Demeter:模块不应了解它操作对象的内部情形。更准确地说,它认为类C的方法f只应该调用以下对象的方法:
- C
- 由f创建的对象;
- 作为参数传递给f的对象;
- 由C实体变量持有的对象。
方法不应该调用任何函数返回对象的方法,除非返回的是数据结构。即智能与朋友聊天,而与陌生人敬而远之。
三、数据传送对象
最为精炼的数据结构是只包含公有变量、没有函数的类。这种结构有时被称为数据传送对象,DTO(Data Transfer Objects)。DTO是非常有用的结构,尤其是在与数据库通信、或者套接字传递消息。更常见的是bean类的结构。豆结构拥有自否赋值器和取值器操作私有变量。这种半封装会显得更OO,当时通常没有任何好处。