GOF23-適配器模式

適配器模式(wrapper包裝者模式):將一個接口轉換成用戶所需要的接口,使相互不兼容的接口一起工作。

例子:筆記本、筆記本電源適配器、交流電。  在各個國家的交流電有些是不相同的,如220V、110V,而筆記本電腦充電電壓基本爲20V(以我的Y7000爲例),是不能直接接入充電的,因此筆記本都配置了一個電源適配器。這就用到了適配器模式

適配器模式中常用的角色

  • Target(目標角色,筆記本20V直流電):目標接口或者類  DC20Tage及其實現類
  • Adapter(適配器,電源適配器):將原角色適配爲目標角色 DC20Adapter及其實現類
  • Adaptee(原角色,110V,220V交流電):需要適配的類 ACAdaptee及其實現類

一、UML類圖

二、代碼

1.Target 目標

package adapter;

public interface DC20Taget {
    int outputDC();
}
package adapter;

/**
 * 目標爲生產出筆記本所需要的電
 */
public class LoptopTaget implements DC20Taget {
    private int voltage;

    public LoptopTaget(int voltage) {
        this.voltage = voltage;
    }

    public int outputDC() {
        return voltage;
    }
}

2.Adaptee 原代碼

package adapter;

public interface ACAdaptee {
    int outputAC();
}
package adapter;

/**
 * 需要適配的110V電源
 */
public class AmericaACAdaptee implements ACAdaptee {
    private final int voltage = 110;
    public int outputAC() {
        return voltage;
    }
}
package adapter;

/**
 * 需要適配的220V電源
 */
public class ChinaACAdaptee implements ACAdaptee {
    private final int voltage = 220;
    public int outputAC() {
        return voltage;
    }
}

3.Adapter 適配器

package adapter;

public interface DC20Adapter {
    boolean support(ACAdaptee ac);
    DC20Taget outputDC20();
}
package adapter;

/**
 * 110V電源適配器,轉換爲筆記本需要的電源並且返回
 */
public class AmericaPowerAdapter implements DC20Adapter {
    private final int voltage = 110;
    private ACAdaptee ac;
    public boolean support(ACAdaptee ac) {
        boolean flag = voltage == ac.outputAC();
        this.ac = flag ? ac: this.ac ;
        return flag;
    }

    public DC20Taget outputDC20() {
        int inputVoltage = ac.outputAC();
        int out = ((Double)(inputVoltage/5.5)).intValue();
        System.out.println("使用AmericaPowerAdapter,輸入電壓"+inputVoltage+"輸出電壓"+out);
        DC20Taget dc20 = new LoptopTaget(out);
        return dc20;
    }
}
package adapter;

/**
 * 220V電源適配器,返回筆記本所需要的電源
 */
public class ChinaPowerAdapter implements DC20Adapter {
    private final int voltage = 220;
    private ACAdaptee ac;
    public boolean support(ACAdaptee ac) {
        boolean flag = voltage == ac.outputAC();
        this.ac = flag ? ac: this.ac;
        return flag;
    }

    public DC20Taget outputDC20() {
        int inputVoltage = ac.outputAC();
        int out = inputVoltage/11;
        System.out.println("使用ChinaPowerAdapter,輸入電壓"+inputVoltage+"輸出電壓"+out);
        DC20Taget dc20 = new LoptopTaget(out);
        return dc20;
    }
}

4.測試代碼

package adapter;

import java.util.LinkedList;
import java.util.List;

public class Client {
    //需要的適配器組
    private List<DC20Adapter> adapters = new LinkedList<DC20Adapter>();
    public Client(){
        this.adapters.add(new ChinaPowerAdapter());
        this.adapters.add(new AmericaPowerAdapter());
    }

    //返回所需要的適配器
    public DC20Adapter getAdapter(ACAdaptee ac) throws Exception {
        DC20Adapter dc20 = null;
        for(DC20Adapter adapter:this.adapters){
            if(adapter.support(ac)){
                dc20 = adapter;
                break;
            }
        }
        if(dc20 == null){
            throw new Exception("沒找到適配器");
        }
        return  dc20;
    }

    
    public static void main(String[] args) throws Exception {
        Client client = new Client();
        ACAdaptee ac220 = new ChinaACAdaptee();
        DC20Adapter adapter = client.getAdapter(ac220);
        DC20Taget dc20Taget = adapter.outputDC20();

        ACAdaptee ac110 = new AmericaACAdaptee();
        adapter = client.getAdapter(ac110);
        DC20Taget dc20Taget1 = adapter.outputDC20();

        System.out.println("ChinaACAdaptee類適配結果"+dc20Taget.outputDC());
        System.out.println("AmericaACAdaptee類適配結果"+dc20Taget1.outputDC());


    }
}

三、總結

適配器模式可以在不改動原有代碼的情況下,滿足新的需求,符合面向對象設計原則對修改關閉對擴展開放。 

適配器模式在SpringMVC 中有很有些的事例,可以參考學習(待源碼跟蹤..........................)。

適配器模式,分爲對象適配器模式、類適配器模式,

  • 對象適配器模式:需要適配的對象在適配器類中以組合的方式存在(使用方便靈活)
  • 類適配器模式:需要適配的對象是適配器的父類(java單繼承,有一定侷限性)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章