設計模式【6.1】-- 初探介面卡模式

秦怀杂货店發表於2021-12-14

設計模式文章集合:http://aphysia.cn/categories/...

開局一張圖,剩下全靠寫...

111

介紹

介面卡模式(百度百科):在計算機程式設計中,介面卡模式(有時候也稱包裝樣式或者包裝)將一個類的介面適配成使用者所期待的。一個適配允許通常因為介面不相容而不能在一起工作的類工作在一起,做法是將類自己的介面包裹在一個已存在的類中。

介面卡模式的主要目的就是為了相容性,把原來不匹配的兩個類或者介面可以協同工作,它屬於結構型模式,主要分為三種:類介面卡,物件介面卡,介面介面卡。

介面卡模式靈活性比較好,可以提高複用性,但是如果濫用,系統呼叫關係會比較複雜,每一次的適配,本質上都是一種妥協

不斷妥協,最後迎來的,必定是重構。

介面卡模式型別

類介面卡

描述:介面卡的類(Adapter),透過繼承原有類,同時實現目標介面,完成的功能是擁有原有類的屬性方法,同時可以呼叫目標介面。
例子:原來一種充電器(目標類)可以給IPhone充電,另一種充電器(介面)可以給Android手機充電,我們想實現一種介面卡可以讓IPhone充電器擁有Android充電器的功能。

程式碼結構如下:

  • AndroidCharger.class:
//給android充電的介面
public interface AndroidCharger {
    public void androidout();
}
  • AppleCharger.class

    //給蘋果充電的類
    public class AppleCharger {
      public void iphoenOut(){
          System.out.println("我是充電器,我可以給蘋果充電...");
      }
    }
    
  • ChagerAdapater.class

    //充電介面卡
    public class ChagerAdapater extends AppleCharger implements AndroidCharger {
      @Override
      public void androidout() {
          iphoenOut();
          System.out.println("介面卡開始工作----");
          System.out.print("我擁有了給Android充電的能力");
      }
    }
  • Test.class

    public class Test {
      public static void main(String[]args){
          ChagerAdapater chagerAdapater = new ChagerAdapater();
          chagerAdapater.androidout();
      }
    }

    執行結果如下:

個人理解:這裡之所以一個繼承一個介面,是因為java只能單繼承,要去適配多個類,只能一個繼承,一個用介面實現,有一定侷限性。重寫它的方法,這也比較靈活,可以對介面方法進行修改。

2.物件介面卡

個人理解:上面所說的類介面卡是透過繼承與實現介面的方式實現(所繼承的父類以及介面都是一個class),物件介面卡就是根據“合成複用原則”,不使用繼承關係,而是使用了關聯關係,直接把另一個類的物件當成成員物件,也就是持有之前需要繼承的類的例項。
程式碼結構沒有改變,只是重新建立了一個包:

  • 更改後的 ChagerAdapater.class

     //充電介面卡
    public class ChagerAdapater implements AndroidCharger {
      //持有蘋果充電器的例項
      private AppleCharger appleCharger;
      //構造器
      public ChagerAdapater(AppleCharger appleCharger){
          this.appleCharger = appleCharger;
      }
      @Override
      public void androidout() {
          System.out.println("介面卡開始工作----");
          System.out.print("我擁有了給Android充電的能力");
      }
    }
  • 更改後的 Test.class

    public class Test {
      public static void main(String[]args){
          ChagerAdapater chagerAdapater = new ChagerAdapater(new AppleCharger());
          chagerAdapater.androidout();
      }
    }

    執行結果沒有改變:

  • 個人理解:這個和第一種類的介面卡其實思想上差不多,只是實現的方式不一樣,類介面卡是透過繼承類,實現介面,物件介面卡是把要繼承的類變成了屬性物件,把例項與介面卡關聯起來,也就是介面卡的類持有了原有父類的物件例項。一般而言,由於java是單繼承,所以我們儘量不要把這一次使用繼承的機會給浪費了,這樣寫也比較靈活。

3.介面介面卡

介面介面卡,也可以稱為預設介面卡模式,或者預設介面卡模式。當我們不需要全部實現介面所實現的方法的時候,我們可以設計一個抽象類去實現介面,然後再這個抽象類中為所有方法提供一個預設的實現,這個抽象類的子類就可以有選擇地對方法進行實現了。
程式碼結構如下:

解釋:學生類可以吃飯,學習,但是教師類也吃飯,但是教師不是學習,而是教書,所以我們把學習吃飯教書當成介面的方法,由於不是所有的類都需要實現所有介面,我們在中間實現了一個抽象類實現這些介面,所有的方法都提供了一個預設是實現方法。然後學生類或者教師類才去繼承抽象類,從而實現自己所需要的一部分方法即可。

  • myInterface.class
//定義介面的方法
public interface myInterface {
    //學習的介面方法
    public void study();
    //教書的介面方法
    public void teach();
    //吃飯的介面方法
    public void eat();

}
  • myAbstractClass.class(抽象類)

    public abstract class myAbstractClass implements myInterface{
      //學習的介面方法
      @Override
      public void study(){}
      @Override
      //吃飯的介面方法
      public void eat(){}
      //教書的介面方法
      @Override
      public void teach(){}
    }
    
  • Student.class(學生類)

    public class Student extends myAbstractClass{
      //學習的介面方法
      @Override
      public void study(){
          System.out.println("我是學生,我要好好學習");
      }
      @Override
      //吃飯的介面方法
      public void eat(){
          System.out.println("我是學生,我要吃飯");
      }
    }
    
  • Teacher.class(教師類)

    public class Teacher extends myAbstractClass {
      @Override
      //吃飯的介面方法
      public void eat(){
          System.out.println("我是教師,我要吃飯");
      }
      //教書的介面方法
      @Override
      public void teach(){
          System.out.println("我是教師,我要教育祖國的花朵");
      }
    }
    
  • Test.calss(測試類)

    public class Test {
      public static void main(String[] args){
          Student student = new Student();
          Teacher teacher = new Teacher();
          student.eat();
          student.study();
          teacher.eat();
          teacher.teach();
      }
    }
    

    執行的結果:

4.總結

1.類介面卡模式主要是透過繼承目標的類,實現要增加的介面方法,就可以把類與介面適配一起工作。

2.物件的介面卡與類介面卡功能大致一樣,但是為了更加靈活,不再使用繼承的方式,而是直接使用了成員變數這樣的方法,將目標的類的物件持有,再實現要增加的介面方法,達到一樣的目的。

3.介面介面卡模式,是把所有的方法定義到一個介面裡面,然後建立一個抽象類去實現所有的方法,再使用真正的類去繼承抽象類,只需要重寫需要的方法,就可以完成適配的功能。
如果有興趣,可以瞭解一下另外一種說法的介面卡模式[https://blog.csdn.net/Aphysia...]

4.建議儘量使用物件的介面卡模式,少用繼承。介面卡模式也是一種包裝模式,它與裝飾模式同樣具有包裝的功能,此外,物件介面卡模式還具有委託的意思。總的來說,介面卡模式屬於補償模式,專門用來在系統後期擴充套件、修改時使用,但要注意不要過度使用介面卡模式。

【作者簡介】
秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。個人寫作方向:Java原始碼解析JDBCMybatisSpringredis分散式劍指OfferLeetCode等,認真寫好每一篇文章,不喜歡標題黨,不喜歡花裡胡哨,大多寫系列文章,不能保證我寫的都完全正確,但是我保證所寫的均經過實踐或者查詢資料。遺漏或者錯誤之處,還望指正。

劍指Offer全部題解PDF

2020年我寫了什麼?

開源程式設計筆記

關注公眾號 ”秦懷雜貨店“ 可以領取劍指 Offer V1版本的 PDF解法,V2版本增加了題目,還在哼哧哼哧的更新中,並且為每道題目增加了C++解法,敬請期待。

相關文章