穿透型方法(pass-through method):除了呼叫另一個方法外幾乎什麼都不做,且被呼叫方法的簽章與自己相似或相同。
真實案例#
某學生 GUI 編輯器專案的 TextDocument 類別:
public class TextDocument ... {
private TextArea textArea;
private TextDocumentListener listener;
...
public Character getLastTypedCharacter() {
return textArea.getLastTypedCharacter();
}
public int getCursorOffset() {
return textArea.getCursorOffset();
}
public void insertString(String textToInsert, int offset) {
textArea.insertString(textToInsert, offset);
}
public void willInsertString(String stringToInsert, int offset) {
if (listener != null) {
listener.willInsertString(this, stringToInsert, offset);
}
}
...
}15 個 public 方法中有 13 個是穿透型方法。
紅旗:穿透型方法(Red Flag: Pass-Through Method)#
穿透型方法只把參數轉送給另一個方法(通常 API 跟自己一樣)。
這通常代表類別之間的職責分割不乾淨。
為什麼有害#
- 使類別變淺:增加介面複雜度,卻沒有增加系統整體功能
- 上述四個方法,只有
willInsertString有實質工作(檢查listener是否為 null),且還很瑣碎
- 上述四個方法,只有
- 製造類別間依賴:底層方法簽章一改,穿透型方法就得跟著改
根本原因#
穿透型方法往往代表類別之間的職責劃分混亂:
TextDocument暴露了insertString,但插入文字的真正邏輯在TextArea內- 一個功能的介面與實作應該位於同一個類別
當你看到一個類別到另一個類別的穿透型方法,問自己:
「這兩個類別到底各自負責哪些特性與抽象?」
通常會發現職責有重疊。
解決方式#
| 方式 | 說明 |
|---|---|
| 直接暴露下層 | 移除上層對該功能的責任,讓上層的呼叫者直接呼叫下層類別 |
| 重新分配 | 在上下兩個類別之間搬移功能,讓它們不再互相呼叫 |
| 合併 | 若兩個類別職責糾結到拆不開,乾脆合併成一個 |

Figure 7.1: 穿透型方法——(a) C1 全是穿透;(b) 直接暴露 C2;(c) 在 C1、C2 之間重分配;(d) 合併兩類別
範例中的學生最後合併了三個類別(TextDocument、TextArea、TextDocumentListener)成兩個,職責也分得更清楚。