重學設(shè)計模式之適配器模式

定義

將一個接口轉(zhuǎn)換成客戶希望的另一個接口,使接口不兼容的那些類可以一起工作壁榕,其別名為包裝器(Wrapper)矛紫。適配器模式既可以作為類結(jié)構(gòu)型模式,也可以作為對象結(jié)構(gòu)型模式牌里。

關(guān)于適配器模式的定義如上已經(jīng)很清楚了颊咬,下面這幅圖可以更清楚的幫助我們理解適配器模式。

適配器作為一個中間件牡辽,將兩個不兼容的類鏈接起來喳篇。

根據(jù)適配器與被適配者類的關(guān)系不同,適配器模式可分為對象適配器和類適配器态辛,在對象適配器模式中麸澜,適配器與適配者之間是關(guān)聯(lián)關(guān)系,在類適配器模式中因妙,適配器與適配者之間是繼承(或?qū)崿F(xiàn))關(guān)系痰憎。

對象適配器模式

UML

適配器模式主要有下面幾個角色:

  • 目標類(Target):目標類定義客戶所需的接口,可以是一個接口攀涵、抽象類或者是一個具體類铣耘。
  • 被適配者類(Adaptee):需要被適配的類,它有自己的方法以故,但不能被目標類直接調(diào)用蜗细,需要通過適配器進行適配。
  • 適配器類(Adapter):通過適配器類對Target和Adaptee進行適配怒详。

前面說過炉媒,對象適配器與類適配器之間的區(qū)別就是,適配器與被適配者之間的關(guān)系昆烁,這里對象適配器中吊骤,適配器與被適配者之間是關(guān)聯(lián)關(guān)系。

適配器的主要代碼如下:

public class Adapter implements Target {

    private  Adaptee adaptee;

    public Adapter() {
        this.adaptee = new Adaptee();
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

類適配器模式

UML

可以看到這里與前面對象適配器的區(qū)別就是適配器與被適配者之間是繼承(或?qū)崿F(xiàn))關(guān)系静尼。

代碼表示如下

public class Adapter extends Adaptee implements Target {

    @Override
    public void request() {
        specificRequest();
    }
    
}

由于在Java中是單繼承的白粉,所以這種類適配器模式的使用會受到限制,如果Target不是接口鼠渺,而是具體類鸭巴,就無法使用類適配器模式了,所以在Java中大部分情況下還是使用對象適配器更多一點拦盹。

實例

還是通過一個實例來理解吧:

軟件公司OA系統(tǒng)需要提供一個加密模塊鹃祖,將用戶機密信息(如口令、郵箱等)加密之后再存儲在數(shù)據(jù)庫中普舆,系統(tǒng)已經(jīng)定義好了數(shù)據(jù)庫操作類恬口。為了提高開發(fā)效率,現(xiàn)需要重用已有的加密算法奔害,這些算法封裝在一些由第三方提供的類中楷兽,有些甚至沒有源代碼。試使用適配器模式設(shè)計該加密模塊华临,實現(xiàn)在不修改現(xiàn)有類的基礎(chǔ)上重用第三方加密方法芯杀。

UML

根據(jù)需求我們可以規(guī)劃結(jié)構(gòu)圖如下:

代碼

主要代碼如下

//加密的工具類
public class EncryptUtils {

    public String MD5Encrypt(String str) {
        String encode = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            BASE64Encoder base64Encoder = new BASE64Encoder();
            encode = base64Encoder.encode(md5.digest(str.getBytes()));
            return encode;
        } catch (NoSuchAlgorithmException e) {
            System.out.println("加密出錯");
            return null;
        }
    }

    public String DESEncrypt(String str) {
        String password = "01234567";
        String encode = null;
        try {
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(password.getBytes());
            //創(chuàng)建一個密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(desKey);
            //Cipher對象實際完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            //用密匙初始化Cipher對象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
            //現(xiàn)在雅潭,獲取數(shù)據(jù)并加密
            //正式執(zhí)行加密操作
            byte[] bytes = cipher.doFinal(str.getBytes());
            BASE64Encoder base64Encoder = new BASE64Encoder();
            encode = base64Encoder.encode(bytes);
            return encode;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    public String RSAEncrypt(String str) {
        return "實現(xiàn)RSA加密返回 ->_->";
    }
}
//目標類
public abstract class EncryptModel {

    abstract String userEncrypt(String str);
}

適配器類

public class EncryptAdapter extends EncryptModel {

    private EncryptUtils encryptUtils;

    public EncryptAdapter() {
        this.encryptUtils = new EncryptUtils();
    }

    @Override
    String userEncrypt(String str) {
        return encryptUtils.MD5Encrypt(str);
    }
}

客戶端代碼

public class Client {

    public static void main(String[] args) {
        EncryptModel encryptModel;

        encryptModel = new EncryptAdapter();

        String encode = encryptModel.userEncrypt("userName");

        System.out.println("加密后的數(shù)據(jù)為:" + encode);
    }
}

運行結(jié)果

加密后的數(shù)據(jù)為:Q14GSNY0F1xGvUCsNmVFqA==

成功通過適配器類使客戶端調(diào)用加密工具類中的加密算法揭厚。

變種--缺省適配器

缺省適配器是適配器模式的一個邊種,在Java中使用也挺廣泛的扶供。

定義

當不需要實現(xiàn)一個接口所提供的所有方法時筛圆,可先設(shè)計一個抽象類實現(xiàn)該接口,并為接口中每個方法提供一個默認實現(xiàn)(空方法)椿浓,那么該抽象類的子類可以選擇性地覆蓋父類的某些方法來實現(xiàn)需求太援,它適用于不想使用一個接口中的所有方法的情況闽晦,又稱為單接口適配器模式。

UML

在Java開發(fā)中我們應(yīng)該都遇到過這種情況提岔,一個接口仙蛉,定義了N種方法,當你使用的時候碱蒙,又僅僅需要使用接口中的一兩個方法荠瘪,但你卻必須實現(xiàn)這個接口中的所有方法,寫了很長一段無意義的代碼赛惩。缺省適配器就是為了解決這種情況哀墓,它通過定一個抽象類實現(xiàn)原始接口,實現(xiàn)接口中的所有方法喷兼,并給所有方法一個默認值或操作篮绰。當需要使用的時候,只需要定義一個類繼承這個抽象類季惯,重寫你所需要的一兩個方法即可阶牍。這個抽象類就是一個缺省適配器。

代碼

原始接口

public interface InterfaceService {
     void serviceOperation1();

     String serviceOperation2();

     int serviceOperation3();

     void serviceOperation4();
}

缺省適配器

public abstract class ServiceAdapter implements InterfaceService {
    @Override
    public void serviceOperation1() {

    }

    @Override
    public String serviceOperation2() {
        return null;
    }

    @Override
    public int serviceOperation3() {
        return 0;
    }

    @Override
    public void serviceOperation4() {

    }
}

具體實現(xiàn)類

public class ConcreteService extends ServiceAdapter {

    @Override
    public void serviceOperation1() {
        System.out.println("serviceOperation1");
    }
}

小結(jié)

適配器模式應(yīng)該是非常常見的一種設(shè)計模式了星瘾,作為Android開發(fā)工程師走孽,我們最常見的應(yīng)該就是各種適配器了,例如ListView和RecycleView的適配器琳状。適配器模式將現(xiàn)有接口轉(zhuǎn)換為客戶端所期望的接口磕瓷,實現(xiàn)了對現(xiàn)有類的復(fù)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末念逞,一起剝皮案震驚了整個濱河市困食,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翎承,老刑警劉巖硕盹,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叨咖,居然都是意外死亡瘩例,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門甸各,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垛贤,“玉大人,你說我怎么就攤上這事趣倾∑傅耄” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵儒恋,是天一觀的道長善绎。 經(jīng)常有香客問我黔漂,道長,這世上最難降的妖魔是什么禀酱? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任瘟仿,我火速辦了婚禮,結(jié)果婚禮上比勉,老公的妹妹穿的比我還像新娘。我一直安慰自己驹止,他們只是感情好浩聋,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著臊恋,像睡著了一般衣洁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抖仅,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天坊夫,我揣著相機與錄音,去河邊找鬼撤卢。 笑死环凿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的放吩。 我是一名探鬼主播智听,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼渡紫!你這毒婦竟也來了到推?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤惕澎,失蹤者是張志新(化名)和其女友劉穎莉测,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唧喉,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡捣卤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了八孝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腌零。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖唆阿,靈堂內(nèi)的尸體忽然破棺而出益涧,到底是詐尸還是另有隱情,我是刑警寧澤驯鳖,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布闲询,位于F島的核電站久免,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扭弧。R本人自食惡果不足惜阎姥,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸽捻。 院中可真熱鬧呼巴,春花似錦、人聲如沸御蒲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厚满。三九已至府瞄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碘箍,已是汗流浹背遵馆。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丰榴,地道東北人货邓。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像四濒,于是被迫代替她去往敵國和親逻恐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容