chapter 6: Objects & Data Structures
1-數據抽象
比較一下代碼:
// 代碼1
public class Point {
public double x;
public double y;
}
VS
// 可表示極座標系 和 直角座標系的點
// 它不止是一個數據結構,因爲他定義了關於數據的訪問
public interface Point {
double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
隱藏實現不是僅僅用一層函數把變量隱藏起來(e.g. set/get),而是抽象!!!
在抽象接口中,我們不想將數據的詳細暴露出來,而想以抽象的方式表達我們的數據。
如以下代碼
// 代碼2
public interface Vehicle {
double getFuelTankCapacityInGallons(); // 獲取總容量
double getGallonsOfGasoline(); // 獲取汽油量
}
VS
public interface Vehicle {
double getPercentFuelRemaining(); // 獲取汽油剩餘百分比
}
2-面向過程和麪向對象的對立
對象將自己的數據隱藏了起來,而把對數據操作的函數暴露出來。而數據結構將數據直接暴露出來,沒有任何操作數據的方法(e.g. C語言的struct)。
- 面向對象: 添加新類別不改變已有函數,但 添加新函數會改變所有現有類別
- 面向過程(數據結構): 添加新函數不會改變現有數據結構,但 添加新的數據結構需要改變所有函數。
代碼示例:
// 代碼3
// 面向過程,添加新函數,不要改變舊數據結構
// 添加新類型,需要改變函數
// 類別1
public class Square {
public Point topLeft; public double side;
}
// 類別2
public class Rectangle {
public Point topLeft;
public double height;
public double width;
}
// 類別3
public class Circle {
public Point center;
public double radius;
}
public class Geometry {
public final double PI = 3.141592653589793;
// 函數1
public double area(Object shape) throws NoSuchShapeException {
if (shape instanceof Square) {
Square s = (Square)shape;
return s.side * s.side;
}
else if (shape instanceof Rectangle) {
Rectangle r = (Rectangle)shape;
return r.height * r.width;
}
else if (shape instanceof Circle) {
Circle c = (Circle)shape;
return PI * c.radius * c.radius;
}
throw new NoSuchShapeException();
}
}
3-Data Transfer Objects: DTO (只含public變量,不含function)
爲了OO思想,很多時候寫出了不必要的代碼,如下
// 代碼4
// 一個只含有數據不含有操作的類,爲了OO, 加了getters&setters
public class Address {
private String street;
private String streetExtra;
private String city;
private String state;
private String zip;
public Address(String street, String streetExtra,
String city, String state, String zip) {
this.street = street;
this.streetExtra = streetExtra;
this.city = city;
this.state = state;
this.zip = zip;
}
public String getStreet() {
return street;
}
public String getStreetExtra() {
return streetExtra;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
public String getZip() {
return zip;
}
}
4-Active Record(對數據庫表映射的類)
Active Records是一種特殊的DTO, 所有數據都是public, 但是它有find和save方法,用來表示數據庫的操作。把他們當做數據結構,而不是對象;不要試圖在其中加入其他東西,使其變得既不是structure, 也不是objects, 而且還擁有兩者的缺點,修改函數要修改類,添加類又要修改函數
5-總結
- object: 暴露操作函數,隱藏數據;添加新類別不改變已有函數,但 添加新函數會改變所有現有類別
- data structure: 暴露數據,沒有真正意義的操作函數。添加新函數不會改變現有數據結構,但 添加新的數據結構需要改變所有函數。
我們應當根據項目的實際情況選擇他們。