設計模式(四)適配器模式

版權聲明:轉載必須註明本文轉自曉_晨的博客:http://blog.csdn.net/niunai112

目錄

導航

設計模式之六大設計原則
設計模式(一)單例模式
設計模式(二)工廠模式
設計模式(三)策略模式
設計模式(四)適配器模式
設計模式(五)享元模式
設計模式(六)建造者模式
設計模式(七)原型模式
設計模式(八)橋接模式
設計模式(九)外觀模式
設計模式(十)組合模式
設計模式(十一)裝飾器模式
設計模式(十二)代理模式
設計模式(十三)迭代器模式
設計模式(十四)觀察者模式
設計模式(十五)中介者模式
設計模式(十六)命令模式
設計模式(十七)狀態模式
設計模式(十八)訪問者模式
設計模式(十九)責任鏈模式
設計模式(二十)解釋器模式
設計模式(二十一)備忘錄模式
設計模式(二十二)模板模式
設計模式總結篇(爲什麼要學習設計模式,學習設計模式的好處)

前言

這篇讓我們學習一下適配器模式,適配器模式是作爲兩個不兼容的接口之間的橋樑。

讓我們設想一下,當一個已經實現好的方法需要A類型的參數,但是我們只有一個可以返回B類型的方法的時候,這個時候該怎麼辦呢?1.修改前面那個的方法,讓他能接受參數A。2.修改後面那個方法,使得他能返回參數A。3.創建一個方法,使得參數B能轉換成A。但基於開閉原則,我們傾向於第三個解決方案,第一種和第二種都需要修改代碼,而且有可能已經有其他的對象已經使用了他們,所以不好在動,但是實際的情況得按具體來分析。這是一個抽象理解。

LZ來舉一個栗子!
當LZ新買了一臺電腦的時候,發現核顯(窮的買不起獨顯)的接口是VGA的接口,但是LZ買到的顯示器卻沒有VGA的接口,有HDMI的接口,這個時候,LZ就只能把VGA轉成HDMI,讓顯示器正常工作。用代碼來展示就如下面所示:

類適配器模式

/***
 *
 *@Author ChenjunWang
 *@Description:VGA接口
 *@Date: Created in 16:02 2018/3/17
 *@Modified By:
 *
 */
public interface VGAInterface {
    public void outputVGASignal();
}



/***
 *
 *@Author ChenjunWang
 *@Description:HDMI接口
 *@Date: Created in 16:03 2018/3/17
 *@Modified By:
 *
 */
public interface HDMIInterface {
    public void outputHDMISignal();

}

/**
 *
 *@Author ChenjunWang
 *@Description:VGA信號輸出類
 *@Date: Created in 15:57 2018/3/17
 *@Modified By:
 *
 */
public class VGA implements VGAInterface{

    public void outputVGASignal(){

        System.out.println("這裏輸出的是VGA的信號");
    }
}
/***
 *
 *@Author ChenjunWang
 *@Description:VGA轉成HDMI的類(適配器類)
 *@Date: Created in 16:03 2018/3/17
 *@Modified By:
 *
 */
public class VGA2HDMI extends VGA implements HDMIInterface {
    @Override
    public void outputHDMISignal() {
        outputVGASignal();
        System.out.println("轉換過程…………");
        System.out.println("輸出HDMI信號");
    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:電腦測試類
 *@Date: Created in 16:03 2018/3/17
 *@Modified By:
 *
 */
public class Computer {
    public static void main(String[] args) {
        VGA2HDMI vga2HDMI = new VGA2HDMI();
        vga2HDMI.outputHDMISignal();
    }
}

輸出結果
--------------------------
這裏輸出的是VGA的信號
轉換過程…………
輸出HDMI信號

UML圖
class

上面的就是類適配器模式了,要繼承輸入的類,自己實現輸出接口。按上面來寫會有一個問題,那就是VGA2HDMI類可以使用VGA的方法,也就是說他能直接輸出VGA信號,但對於程序猿來說,應該把錯誤防範於未然,那就是讓外面看不到裏面有這個方法。

對象適配器模式

在這裏LZ只修改了VGA2HDMI類,他不在需要繼承VGA了,內部有個VGA的私有變量,這樣以來,按正常流程來走(不包括反射),外界就看不到裏面有VGA這個字段,而且也調用不到方法了,當初始化的時候,外部傳入VGA的類,裏面就能直接得到裏面的東西了,在這裏是VGA的信號,然後實現outputHDMISignal方法將信號轉爲HDMI。

第二個修改的類是Computer,在實例化適配器VGA2HDMI的時候,需要傳入VGA的實例,否則無法轉換,因爲都沒信號輸入了,沒有辦法轉換啊。

import adapter.HDMIInterface;

public class VGA2HDMI  implements HDMIInterface {
    private VGA vga;
    VGA2HDMI(VGA vga){
        this.vga = vga;
    }
    @Override
    public void outputHDMISignal() {
        vga.outputVGASignal();
        System.out.println("轉換過程…………");
        System.out.println("輸出HDMI信號");
    }
}

public class Computer {
    public static void main(String[] args) {
        VGA2HDMI vga2HDMI = new VGA2HDMI(new VGA());
        vga2HDMI.outputHDMISignal();
    }
}
運行結果
------------------------------------------------
這裏輸出的是VGA的信號
轉換過程…………
輸出HDMI信號

UML圖
object

接口適配器模式(缺省適配器模式)

當一個接口的方法聲明太多的時候,有點子類不需要實現這麼多方法。比如一個屏幕的接口,他抽象出了能得到VGA,HDMI,DVI,DP信號的方法。但是,實際上,到手的顯示器都沒有這麼多的接口可以用,有其中的2-3個接口。
比如一塊X牌子的顯示器,只能接收VGA和HDMI信號,那麼他的另外2個方法就得爲空了,因爲他沒辦法處理。

/***
 *
 *@Author ChenjunWang
 *@Description:屏幕接口
 *@Date: Created in 16:58 2018/3/17
 *@Modified By:
 *
 */
public interface Screen {
    public void getVGASignal();
    public void getHDMISignal();
    public void getDVISignal();
    public void getDPSignal();
}

/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 17:01 2018/3/17
 *@Modified By:
 *
 */
public class XSrceen implements Screen {
    @Override
    public void getVGASignal() {
        System.out.println("顯示器顯示!");
    }

    @Override
    public void getHDMISignal() {
        System.out.println("顯示器顯示!");
    }

    @Override
    public void getDVISignal() {

    }

    @Override
    public void getDPSignal() {

    }
}

這個時候,就可以創建一個類默認實現了裏面所有的方法,其實是不做任何處理,這個時候一個Y牌的顯示器繼承默認的顯示器,只需要重寫自己想要的方法就行了。

/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 17:03 2018/3/17
 *@Modified By:
 *
 */
public class DefaultScreen implements Screen{
    @Override
    public void getVGASignal() {

    }

    @Override
    public void getHDMISignal() {

    }

    @Override
    public void getDVISignal() {

    }

    @Override
    public void getDPSignal() {

    }
}


/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 17:04 2018/3/17
 *@Modified By:
 *
 */
public class YScreen extends DefaultScreen {
    @Override
    public void getHDMISignal() {

        System.out.println("顯示器顯示!");
    }

    @Override
    public void getDVISignal() {

        System.out.println("顯示器顯示!");
    }
}

uml圖
default
因爲接口設計的最小化只是理想狀態,難免會有一些實現類,對其中某些方法不感興趣,這時候,如果方法過多,子類也很多,並且子類的大部分方法都是空着的,那麼就可以採取這種方式了。可以減少類裏面的代碼量。

當然,這樣做違背了里氏替換原則,但是上面的做法原本就違背了接口的最小化原則,所以我們在真正使用時要權衡二者的利弊,到底我們需要的是什麼。所以從此也可以看出來,原則只是指導,並不一定也不可能全部滿足,所以我們一定要學會取捨。

各種規則畢竟都只是理想化的東西,在實際項目中應該根據實際情況進行合理的變通。假如你是超級無敵大牛,那可以無視LZ說的話~~~~

Git地址

本篇實例Github地址:https://github.com/stackisok/Design-Pattern/tree/master/src/adapter

回到最上方


有什麼不懂或者不對的地方,歡迎留言。
喜歡LZ文章的小夥伴們,可以關注一波,也可以留言,LZ會回你們的。
覺得寫得不錯的小夥伴,歡迎轉載,但請附上原文地址,謝謝^_^!

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