大話設計模式筆記(十四)の適配器模式

舉個栗子

問題描述

不一樣國家的人在NBA打球,但都是用英文交流。編程

簡單實現

Player

/**
 * 球員
 * Created by callmeDevil on 2019/8/4.
 */
public abstract class Player {

    protected String name;

    public Player(String name){
        this.name = name;
    }

    // 發起進攻
    public abstract void attack();
    // 轉回防守
    public abstract void defense();

}

Forwards

/**
 * 前鋒
 * Created by callmeDevil on 2019/8/4.
 */
public class Forwards extends Player {

    public Forwards(String name){
        super(name);
    }

    @Override
    public void attack() {
        System.out.println(String.format("前鋒 %s 進攻", name));
    }

    @Override
    public void defense() {
        System.out.println(String.format("前鋒 %s 防守", name));
    }
}

Center

/**
 * 中鋒
 * Created by callmeDevil on 2019/8/4.
 */
public class Center extends Player {
    // 代碼與前鋒類似
}

Guards

/**
 * 後衛
 * Created by callmeDevil on 2019/8/4.
 */
public class Guards extends Player {
    // 代碼與前鋒類似
}

測試

public class Test {
    public static void main(String[] args) {
        Player b = new Forwards("巴蒂爾");
        b.attack();
        Player m = new Guards("麥克格雷迪");
        m.attack();

        Player ym = new Center("姚明");
        // 姚明問:attack 和 defense 是什麼意思?
        ym.attack();
        ym.defense();
    }
}

測試結果

前鋒 巴蒂爾 進攻
後衛 麥克格雷迪 進攻
中鋒 姚明 進攻
中鋒 姚明 防守

存在問題

姚明剛到NBA時可能英文還不太好,也就是說聽不懂教練的戰術安排,attach 和 defense 不知道什麼意思,所以這樣實現會有問題,須要一箇中英翻譯。ide

適配器模式

定義

將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。測試

分類

主要分爲類適配器模式對象適配器模式。因爲類適配器模式經過多重繼承對一個接口與另外一個接口進行匹配,而 Java 等語言不支持多重繼承,也就是一個類只有一個父類,因此這裏主要講的是對象適配器this

UML圖

代碼實現

ForeignCenter

/**
 * 外籍中鋒
 * Created by callmeDevil on 2019/8/4.
 */
public class ForeignCenter {

    // 外籍中鋒球員的姓名故意用屬性而不是構造方法來區別與三個球員的不一樣
    private String name;

    // 代表外籍中鋒只懂中文「進攻」(注意:舉例效果,實際上千萬別用這種方式編程)
    public void 進攻(){
        System.out.println(String.format("外籍中鋒 %s 進攻", name));
    }

    // 代表外籍中鋒只懂中文「防守」(注意:舉例效果,實際上千萬別用這種方式編程)
    public void 防守(){
        System.out.println(String.format("外籍中鋒 %s 防守", name));
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Translator

/**
 * 翻譯者
 * Created by callmeDevil on 2019/8/4.
 */
public class Translator extends Player{

    // 聲明並實例化一個內部「外籍中鋒」對象,代表翻譯者與外籍球員有關聯
    private ForeignCenter wjzf = new ForeignCenter();

    public Translator(String name){
        super(name);
        wjzf.setName(name);
    }

    @Override
    public void attack() {
        // 翻譯者將「attack」翻譯爲「進攻」告訴外籍中鋒
        wjzf.進攻();
    }

    @Override
    public void defense() {
        // 翻譯者將「defense」翻譯爲「防守」告訴外籍中鋒
        wjzf.防守();
    }

}

測試

public class Test {
    public static void main(String[] args) {
        Player b = new Forwards("巴蒂爾");
        b.attack();
        Player m = new Guards("麥克格雷迪");
        m.attack();

        Player ym = new Translator("姚明");
        // 翻譯者告訴姚明,教練要求你既要「進攻」又要「防守」
        ym.attack();
        ym.defense();
    }
}

測試結果

前鋒 巴蒂爾 進攻
後衛 麥克格雷迪 進攻
外籍中鋒 姚明 進攻
外籍中鋒 姚明 防守

總結

  • 系統的數據和行爲都正確,但接口不符時,咱們應該考慮用適配器,目的是使控制範圍以外的一個原有對象與某個接口匹配。
  • 適配器模式主要應用於但願複用一些現存的類,可是接口又與複用環境要求不一致的狀況。
  • 使用已經存在的類,但若是它的接口,也就是它的方法和你的要求不相同時,就應該考慮用適配器模式。
  • 兩個類所作的事情相同或類似,可是具備不一樣的接口時要使用它。
  • 客戶代碼能夠統一調用同一接口就好了,這樣能夠更簡單、直接、緊湊。
  • 在雙方都不太容易修改的時候再使用適配器模式適配。
相關文章
相關標籤/搜索