必要的介面
2015 年 10 月 12 日
必要的介面是由互動客戶端定義的介面,用於指定供應元件在互動中需要執行的動作。
「可比較」介面是一個必要的介面範例。此類介面通常是排序功能所需要的。假設我有一組專輯,我想依照標題排序,但忽略「The」、「A」和「An」等冠詞。我可以透過實作任何排序功能的必要介面,讓專輯以這種方式排序。

在 Java 中,它會類似這樣。
class Album...
public class Album implements Comparable<Album> { private String title; public Album(String title) { this.title = title; } public String getTitle() { return title; } @Override public int compareTo(Album o) { return this.sortKey().compareTo(o.sortKey()); } private String sortKey() { return ignoreSortPrefixes(title).toLowerCase(); } private static String ignoreSortPrefixes(String arg) { final String[] prefixes = {"an", "a", "the"}; return Arrays.stream(prefixes) .map(s -> s + " ") .filter(s -> arg.toLowerCase().startsWith(s)) .findFirst() .map(s -> arg.substring(s.length(), arg.length())) .orElse(arg) ; }
在本例中,Comparable
是各種 Java 排序功能的必要介面。更複雜的範例可能會有更豐富的介面,並在其中定義多種方法。
人們通常認為介面是供應商關於對客戶端公開什麼內容的決策。但必要的介面是由客戶端指定(且通常定義)的。透過思考客戶端需要什麼,你通常可以獲得更有用的介面,這會引導你思考 角色介面。
使用適配器
如果我想將兩個獨立定義的模組整合在一起,會出現一個常見的問題。即使我們獲得相符的名稱,我們也可能會遇到困難。
考慮一個任務清單,其必要的介面為任務。
class TaskList...
private List<Task> tasks; private LocalDate deadline; public LocalDate latestStart() { return deadline.minusDays(tasks.stream().mapToInt(t -> t.shortestLength()).sum()); } }
interface Task…
int shortestLength();
假設我想將它與從不同供應商取得的 Activity
類別整合。
class Activity…
public int shortestLength() { …
即使活動有一個方法簽章剛好與必要的介面相符,我(正確地)無法建立活動的任務清單,因為類型定義不符。如果我無法修改活動類別,我需要使用適配器。
public class ActivityAdapter implements Task { private Activity activity; public ActivityAdapter(Activity activity) { this.activity = activity; } @Override public int shortestLength() { return activity.shortestLength(); } }
在軟體世界中,我們很自由地使用適配器這個術語,但這裡我嚴格按照 四人幫書籍 的意義來使用。在此用法中,適配器是一個將一個物件對應到另一個物件的必要介面的物件。

在本例中,如果我使用的是動態語言,我不需要適配器,但如果活動類別使用具有不同簽章的方法,我則需要適配器。