類別繼承非精確重用機制:無法單獨重用某方法,帶來多餘成員與耦合。解決方案:將單一職責方法提煉為獨立靜態方法,僅依賴輸入參數,無外部狀態。
class Polygon {
public int getPerimeter() { ... }
public boolean isConvex() { ... }
public boolean containsPoint(Point p) { ... }
}
class Polygon {
public int getPerimeter() { return pPolygon.computePerimeter(this); }
public boolean isConvex() { return pPolygon.isConvex(this); }
public boolean containsPoint(Point p) { return pPolygon.containsPoint(this, p); }
}
class pPolygon { // 命名慣例:p 開頭表示純過程類
static public int computePerimeter(Polygon polygon) { ... }
static public boolean isConvex(Polygon polygon) { ... }
static public boolean containsPoint(Polygon polygon, Point p) { ... }
}
客戶代碼無需繼承 Polygon,直接呼叫所需靜態方法。類別仍負責封裝資料,但行為邏輯外移,降低複雜度與耦合。
Allen Holub 指出:真正重用在於「針對介面而非類別編程」。參數型別為介面時,方法可操作所有實作該介面的物件,甚至尚未存在的類別。
// 具體類別參數
static public boolean contains(Rectangle rect, int x, int y) { ... }
// 介面參數
static public boolean contains(Rectangular rect, int x, int y) { ... }
public interface Rectangular {
Rectangle getBounds();
}
所有可描述為矩形的類別(視窗、按鈕、圖片...)實作 Rectangular 即可傳入。集合處理時更顯威力:
static public boolean areAnyOverlapping(Collection<Rectangular> rects) {
for (Rectangular r : rects) { ... } // 無需知道具體類別
}
介面方法越少,實作類別越多,重用範圍越廣。Window 碰撞檢測僅需矩形座標:
// 過度綁定 Window
static public boolean areOverlapping(Window w1, Window w2) { ... }
// 精簡介面
static public boolean areOverlapping(Rectangular r1, Rectangular r2) { ... }
static public void sort(List list, SortComparison comp) { ... }
public interface SortComparison {
boolean comesBefore(Object a, Object b);
}
SortComparison 僅提供排序所需的比較鉤子,不可再重用他處——這正是「最簡單介面」的極致。