对象和数据结构之间是截然对立的,它们之间存在着二分原理:使用数据结构的代码便于在不改动既有数据结构的前提下添加新的函数,面向对象代码(接口)便于在不改动既有函数的前提下添加新类。因为数据结构代码,在添加新的数据结构的时候,必须修改所有的函数,面向对象的代码难以添加新的函数,因为必须修改所有的类。
//数据结构,直接暴露内部数据
public class Point(){
public double x;
public double y;
}
//对象,隐藏了数据结构,提供操作方法
public class Point(){
private double x;
private double y;
public double getX();
public double getY();
void setCartesian(double x, double y);
}
1.德墨忒尔律
模块不应了解它所操作对象的内部情形,对象隐藏数据,暴露操作,方法不应调用由任何函数反对的对象的方法,即之和朋友谈话,不和朋友的朋友(陌生人)谈话。
//反例
final String outPutDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
//正例
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outPutDir = scratchDir.getAbsolutePath();
2.混杂
有时会出现一半对象,一半数据结构的情况,这种结构拥有执行操作的函数,也有公共变量或公共访问器及改值器。此类混杂增加了添加新数据的难度,也增加了添加新函数的难度,,应该避免创建这种结构。
3.数据传输对象
最为精炼的数据结构,是只有一个公共变量,没有函数的类。这种数据结构有时被称为数据传送对象,或DTO,这是一种非常有用的数据结构,尤其是在与数据库通信,或解析套接字传递的消息等场景中。
public class ListDeptDTO extends BaseDTO implements Serializable {
private static final long serialVersionUID = -4869594085374385813L;
/**
* 部门名称
*/
private String deptName;
/**
* 部门Id
*/
private String deptId;
/**
* 开始时间
*/
private String createTimeFrom;
/**
* 结束时间
*/
private String createTimeTo;
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getDeptId() {
return deptId;
}
public void setDeptId(String deptId) {
this.deptId = deptId;
}
public String getCreateTimeFrom() {
return createTimeFrom;
}
public void setCreateTimeFrom(String createTimeFrom) {
this.createTimeFrom = createTimeFrom;
}
public String getCreateTimeTo() {
return createTimeTo;
}
public void setCreateTimeTo(String createTimeTo) {
this.createTimeTo = createTimeTo;
}
}
4.Active Record
Active Record是一种特殊的DTO形式,它们拥有公共的变量,但通常也会拥有类似save,find这样的浏览方法,Active Record一般是对数据库表或者其他数据源的直接翻译。