Java 從基礎到精通 — 第 3 講
設計物件、封裝和不可變值
該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。
物件將相關狀態和行為綁定在單一邊界內。 封裝並不是無條件隱藏字段,而是將規則放入類別中,以便只能創建有效的狀態。
使用建構函數建立有效對象
public final class Player {
private final String name;
private int health;
public Player(String name, int health) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("name is required");
}
this.name = name;
this.health = Math.max(0, health);
}
public void takeDamage(int amount) {
if (amount > 0) {
health = Math.max(0, health - amount);
}
}
public int getHealth() {
return health;
}
}
外界無法直接改變健康;它只透過名為 takeDamage 的規則來更改它。 建構函數完成的物件滿足名稱和健康有效的條件。
引用可以指向同一個對象
Player first = new Player("Rose", 100);
Player second = first;
second.takeDamage(20);
System.out.println(first.getHealth()); // 80
在第二個例子中,物件沒有被複製,但指向同一個 Player 的引用被複製。 如果需要獨立副本,則必須明確設計要複製哪些欄位。
建立不可變的值
public final class ItemKey {
private final int id;
private final String grade;
public ItemKey(int id, String grade) {
this.id = id;
this.grade = grade;
}
}
如果將欄位設為最終欄位並且不提供變更方法,則其狀態在建立後不會變更。 但是,如果該欄位是可變集合,則應考慮防禦性複製或唯讀視圖。
物件設計的重點不是同時創建 getter 和 setter。 誰可以改變狀態以及必須始終維持什麼條件透過類別的公共方法來表達。