Java 設計模式(一)《介面卡模式》

lvgo發表於2018-08-23

介面卡模式

  • 型別: 結構型
  • 難度:入門級

更多設計模式小故事案例程式碼詳解 >>點我!點我!點我!<< 設計模式,如此簡單~


別名

Wrapper (包裝)(介面卡模式(Adapter Pattern)和裝飾器模式(Decorator Pattern)的統稱)


設計目的

將一個類的介面轉換成客戶希望的另外一個介面。介面卡模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。


釋義

生活中的例子

你有一個張記憶體卡,有一臺電腦,你現在想要看記憶體卡上的照片,想聽記憶體卡上的歌,想看記憶體卡上的電影,但是你直接插電腦上又插不上去,所以你需要一個介面卡,那就是讀卡器。這樣你的記憶體卡就可以在電腦上執行了。

你的iphone x的手機,想要聽歌,但是耳機忘記帶了,所以和我來借,可是我是國產的OPPO,所以你從包裡拿出來一個轉換插頭,讓耳機插到轉換插頭上,再插到手機上,這個轉換插頭就是介面卡。

侵華的日本鬼子當年侵華無法和我們溝通,結果你猜怎麼著,那個漢奸就是介面卡,他把日語轉成了中文,把中文轉成了日語。勿忘國恥!

簡單來講

介面卡模式可以讓你在介面卡中包裝一個與另一個物件不相容的物件,使其相容。

來自維基百科的解釋

將一個類的介面轉接成使用者所期待的。一個適配使得因介面不相容而不能在一起工作的類能在一起工作,做法是將類自己的介面包裹在一個已存在的類中。


程式碼例項講解

有一個船長,只會使用划艇,不會使用漁船。

首先,我們有介面RowingBoatFishingBoat

public interface RowingBoat {
  void row();
}

public class FishingBoat {
  private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);
  public void sail() {
    LOGGER.info("The fishing boat is sailing");
  }
}
複製程式碼

並且船長本身是會划艇的,所以船長已經實現了這個介面。

public class Captain implements RowingBoat {

  private RowingBoat rowingBoat;

  public Captain(RowingBoat rowingBoat) {
    this.rowingBoat = rowingBoat;
  }

  @Override
  public void row() {
    rowingBoat.row();
  }
}
複製程式碼

現在來了一個海盜,並且只有漁船可以使用,我們的船長想要逃避海盜,就只能使用漁船。所以我們需要一個介面卡來幫助船長來用他操作划艇的技術來操作漁船。

public class FishingBoatAdapter implements RowingBoat {

  private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoatAdapter.class);

  private FishingBoat boat;

  public FishingBoatAdapter() {
    boat = new FishingBoat();
  }

  @Override
  public void row() {
    boat.sail();
  }
}
複製程式碼

現在,船長既可以開著漁船逃避海盜了。

Captain captain = new Captain(new FishingBoatAdapter());
captain.row();
複製程式碼

完整程式碼傳送 >>>


使用契機

什麼時候使用介面卡模式?

  • 你想使用現有的類,但是這個類的介面不符合你所需要的。
  • 你現在想要建立一個類,用在一些彼此之間沒有太大關聯的類,包括一些以後將來引進的類一起工作。這些類不一定有一致的介面。
  • 通過介面轉換,將一個類插入另一個類系中。(比如老虎和飛禽,現在多了一個飛虎,在不增加實體的需求下,增加一個介面卡,在裡面包容一個虎物件,實現飛的介面。)
  • 大多數使用第三方庫的應用程式使用介面卡作為應用程式和第三方庫之間的中間層,以將應用程式與庫解耦。如果必須使用另一個庫,則只需要為新庫新增介面卡,而不必更改應用程式程式碼。

結論:

類介面卡和物件介面卡的區別

類介面卡

  • 通過提交到具體的需要適配的類來使介面卡來適應目標類。 因此,當我們想要調整類及其所有子類時,類介面卡將不起作用。
  • 讓介面卡覆蓋一些適配者的行為, 因為介面卡是適配者的子類。
  • 只需要引入一個物件,不需要其他的指標來間接的指向介面卡。
  • 介面卡Adapter繼承我們的被適配者Adaptee,並實現目標介面。由於Java中是單繼承,所以這個介面卡僅僅只能服務於所繼承的被適配者Adaptee

物件介面卡

  • 介面卡實現我們的目標介面,但是並不繼承需要被適配的類。而是通過在介面卡的建構函式中將需要被適配的類傳遞進來從而進行適配
  • 讓一個介面卡與許多適配者一起工作 - 即適配者本身及其所有子類(如果有的話)。 介面卡還可以立即向所有適配者新增功能。
  • 覆蓋適配者Adaptee的方法複雜困難,需要介面卡使用一個適配者的子類,不能直接引用適配者。

優缺點

優點:

  1. 可以讓任何兩個沒有關聯的類一起執行。
  2. 提高了類的複用。
  3. 增加了類的透明度。
  4. 靈活性好。

缺點:

  1. 過多地使用介面卡,會讓系統非常零亂,不易整體進行把握。比如,明明看到呼叫的是 A 介面,其實內部被適配成了 B 介面的實現,一個系統如果太多出現這種情況,無異於一場災難。因此如果不是很有必要,可以不使用介面卡,而是直接對系統進行重構。
  2. 由於 JAVA 至多繼承一個類,所以至多隻能適配一個適配者類,而且目標類必須是抽象類。

jdk中使用到此模式的地方

JDK 1.9 中英文 chm 文件下載


參考文獻

相關文章