適配器模式

適配器使用場景

當系統依賴的接口提供了需要的功能,但是接口簽名並不是完全匹配時,就可以使用適配器模式,將外部接口橋接到內部系統上。

代碼實例

依賴接口

public interface RemoteCallBackA {
    void doCallBackA();
}

public interface RemoteCallBackB {
    void doCallBackB();
}

業務邏輯

public class BuzLogic {
    public void doLogic(Object callBack) { //做完自身業務邏輯後回調外部接口
        System.out.println("do business start");
        System.out.println("do business end");
        if (callBack instanceof RemoteCallBackA) {
            ((RemoteCallBackA) callBack).doCallBackA();
        } else if (callBack instanceof RemoteCallBackB) {
            ((RemoteCallBackB) callBack).doCallBackB();
        }
    }
}

自己的業務BuzLogic需要回調2個外部系統的接口,但外部接口簽名不通用,只能通過instanceof來進行區分;當增加一個外部系統時,必然會修改BuzLogic的核心功能;違背開閉原則。設計的原則是封裝變化的點,這裏變化的點是外部系統簽名不同,因此可以使用適配器模式封裝這一變化。 

使用適配器模式的代碼

public interface CallBackAdapter {
    public void callBack(Object target);

    public boolean supports(Object remoteInterface);
}

public class CallBackAdapterA implements CallBackAdapter {
    public void callBack(Object target) {
        RemoteCallBackA remoteCallBackA = (RemoteCallBackA)target;
        remoteCallBackA.doCallBackA();
    }

    @Override
    public boolean supports(Object remoteInterface) {
        return remoteInterface instanceof RemoteCallBackA;
    }
}

public class CallBackAdapterB implements CallBackAdapter {
    @Override
    public void callBack(Object target) {
        RemoteCallBackB remoteCallBackA = (RemoteCallBackB)target;
        remoteCallBackA.doCallBackB();
    }

    @Override
    public boolean supports(Object remoteInterface) {
        return remoteInterface instanceof RemoteCallBackB;
    }
}

public class BuzLogic {
    CallBackAdapter[] callBackAdapterArray = new CallBackAdapter[]{new CallBackAdapterA(),new CallBackAdapterB()};

    public void doLogic(Object callBack) {
        System.out.println("do business start");
        System.out.println("do business end");
        CallBackAdapter adapter = getCallBackAdapter(callBack);
        adapter.callBack(callBack);
    }

    private CallBackAdapter getCallBackAdapter(Object callBack) {
        for (CallBackAdapter adapter : callBackAdapterArray) {
            if (adapter.supports(callBack)) {
                return adapter;
            }
        }
        return null;
    }
}

之後如果要增加外部系統,只需要添加一個Adapter就可以了,無需修改doLogic代碼。

適配器模式引發的思考

拋開具體代碼,這個模式帶給我們的啓發是通過繼承和循環替代if/else達到代碼的整潔。在擴展功能時由於使用了if/else需要修改業務邏輯,導致違背開閉原則,不便於橫向擴展 。適配器模式封裝這種變化消除if/else,把每個變化分支放到一個子類中去,在上面的例子中supports和callBack組成一個分支;然後通過父類將所有變化點組織起來,並通過for循環的方式去遍歷每個分支;當增加新的分支時,添加一個新的子類而無需修改for循環,達到對新增開發對修改封閉。這種編碼的思想應該牢記於心,當複雜業務邏輯使用if/else橫向擴展時,就應該通過設計模式封裝變化。

另外一種類適配器以MouseAdapter爲例,它實現了MouseListener, MouseWheelListener, MouseMotionListener這3個接口,併爲所有方法生成了一個空實現方便子類使用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章