Java進階篇設計模式之四 -----適配器模式和橋接模式

来源:https://www.cnblogs.com/xuwujing/archive/2018/08/22/9520851.html
-Advertisement-
Play Games

前言 在 "上一篇" 中我們學習了創建型模式的建造者模式和原型模式。本篇則來學習下結構型模式的適配器模式和橋接模式。 適配器模式 簡介 適配器模式是作為兩個不相容的介面之間的橋梁。這種類型的設計模式屬於結構型模式,它結合了兩個獨立介面的功能。 簡單的來說就是通過某個介面將不相容的兩個類進行相容,俗稱 ...


前言

上一篇中我們學習了創建型模式的建造者模式和原型模式。本篇則來學習下結構型模式的適配器模式和橋接模式。

適配器模式

簡介

適配器模式是作為兩個不相容的介面之間的橋梁。這種類型的設計模式屬於結構型模式,它結合了兩個獨立介面的功能。

簡單的來說就是通過某個介面將不相容的兩個類進行相容,俗稱轉換器。
生活比較典型的例子是電器的電壓,美國的電壓是110V左右, 而中國的電壓普片是220V,如果我們想用美國或日本的電器,則需要一個轉換器,將110V轉換成220V。還有一個很典型例子就是曾經的萬能充,基本可以充各種手機的電池。

這裡我們用一個簡單的示例來進行說明。
某個視頻播放器,只能播放MP4格式的視頻,但是主流的視頻格式除了MP4,還有AVI、RVMB等,這時就有個軟體,格式工廠用於對視頻格式的轉換(適配器),從而進行播放視頻。這時我們就可以使用適配器模式來進行完成該代碼的編寫。

適配器模式主要有兩種類型,一種是類適配器模式,主要通過繼承來實現適配器功能;一種是對象適配器模式,通過組合來實現適配器功能。

首先是類適配器模式,它需要完成一下步驟:

  1. 建立MP4、AVI、RVMB視頻格式的介面;
  2. 建立一個視頻播放器的類實現MP4視頻格式的類;
  3. 編寫一個格式工廠類,將AVI、RVMB等格式的視頻文件轉換成MP4格式的文件。
  4. 播放這些視頻。

那麼代碼如下:

代碼示例:


    interface Mp4{
        void playMp4();
    }
    
    interface Avi{
        void playAvi();
    }
    
    
    interface Rvmb{
        void playRvmb();
    }
    
    class VideoPlayer implements Mp4{
    
        @Override
        public void playMp4() {
            System.out.println("播放Mp4格式的視頻文件.");
        }
    }
    
    
    class FormatFactory extends VideoPlayer  implements Avi{    
        @Override
        public void playAvi() {
            //轉換成MP4格式的視頻
            playMp4();
        }
    }
    
    
    public static void main(String[] args) {        
            Mp4 mp4=new VideoPlayer();
            mp4.playMp4();
            Avi avi=new FormatFactory();
            avi.playAvi();
    }

運行結果:

    播放Mp4格式的視頻文件.
    播放Mp4格式的視頻文件.

通過上述代碼以及運行結果,我們可以得到想要的結果了,如果還有新增的視頻格式,也需要使用該視頻播放器播放的話,只需在增加一個介面以及格式工廠類就可以了。

對象適配器模式
通過組合來實現適配器功能。
所以這裡我們只需將格式工廠中繼承改為創建對象即可。
更改之後的代碼如下:
代碼示例


class FormatFactory2  implements Rvmb{
        private Mp4 mp4;
        
         public FormatFactory2(Mp4 mp4) {
            this.mp4=mp4;
        }
        
        @Override
        public void playRvmb() {
            mp4.playMp4();
        }   
    }


    public static void main(String[] args) {
    
            Rvmb rvmb=new FormatFactory2(new VideoPlayer());
            rvmb.playRvmb();
            
    }

運行結果:

    播放Mp4格式的視頻文件.

這兩種適配器模式中,都實現了該功能,不過在這裡推薦使用對象適配器模式,相比類適配器模式,它更加靈活,也符合設計原則中的合成復用原則:

儘量使用合成/聚合的方式,而不是使用繼承。

適配器模式的優點:

提升了類的復用和靈活度。

適配器模式的缺點:

使用過多,系統會比較雜亂,難以把握。

註意事項:

適配器不是在詳細設計時添加的,而是解決正在服役的項目的問題。

橋接模式

簡介

橋接是用於把抽象化與實現化解耦,使得二者可以獨立變化。這種類型的設計模式屬於結構型模式,它通過提供抽象化和實現化之間的橋接結構,來實現二者的解耦。

字面的意思解讀就是通過一個中間的橋梁對兩邊的東西進行關聯起來,但是關聯的兩者之間又不相互影響。對這個印象比較深的是<大話設計模式>中的手機品牌和手機軟體,手機有很多品牌,市場有很多軟體,每個手機裝的軟體又各不相同,手機品牌包含包含軟體,但是軟體並不是手機的一部分,它們是聚合關係。如果A品牌手機裝了a,b軟體,B品牌手機裝了b,c軟體,如果A品牌手機需要新安裝一個c軟體,那麼它只需添加該軟體即可,無需知道該軟體是如何生產的。相同的,如果新增了一個C品牌手機,那麼它也只需安裝所需的a、b或c軟體即可。

好了,廢話不在多說,依舊用一個示例來進行說明。
市面上有很多種筆,比如鉛筆、黑色的圓珠筆和紅色的圓珠筆等等, 也有很多種類型的紙,比如考試的卷子用的紙,報紙用的紙等等。一般來說,報紙上的字顏色是黑色的,這裡我們就用黑色的圓珠筆來進行書寫,考試卷子上的打分字顏色是紅色的,這裡我們就用紅色的圓珠筆來進行書寫。筆類和紙類相互獨立,但是在紙上寫字又將它們關聯起來,這裡我們就可以使用橋接模式。

實現步驟如下:

  1. 定義一個筆類的介面,有寫的這個方法;
  2. 定義紅筆和黑筆的類,實現筆類的介面;
  3. 定義一個紙類的抽象類,設置筆的種類,並需要實現被寫的方法;
  4. 定義卷子紙和新聞紙類,繼承紙類並實現該方法;
  5. 進行書寫。

代碼示例


interface Pen{
    void write();
}

class RedPen implements Pen{
    @Override
    public void write() {
        System.out.println("紅色的字");
    }
}

class BlackPen implements Pen{
    @Override
    public void write() {
        System.out.println("黑色的字");
    }
}


abstract class  Paper{
    protected  Pen pen;
    
    void setPen(Pen pen){
        this.pen=pen;
    }   
    abstract void writing();
}

class ExaminationPaper extends Paper{
    @Override
    void writing() {
        pen.write();
    }
}

class NewsPaper extends Paper{
    @Override
    void writing() {
        pen.write();
    }
}

public static void main(String[] args) {
        Paper paper=new ExaminationPaper();
        paper.setPen(new RedPen());
        paper.writing();
        
        Paper paper2=new NewsPaper();
        paper2.setPen(new BlackPen());
        paper2.writing();
    }

運行結果

紅色的字
黑色的字

從上述結果中我們可以得出我們想要的結果。如果新增一個筆類或者一個紙類,那麼只需新增相應的介面和實現即可,並不會因為結構化改變而相互直接影響。

橋接模式的優點:

1、抽象和實現的分離,實現瞭解耦;
2、提升的擴展能力。

橋接模式的缺點:

會使系統看起複雜,對新手不友好,沒有一定的抽象進行設計能力難以理解。

使用場景:

一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。

其它

音樂推薦

網易雲網友評價(ps:原版無法生成外鏈,建議聽原版):

扶桑畫師淺溪,居泰安,喜繪鯉。院前一方荷塘,錦鯉游曳,溪常與嬉戲。 其時正武德之亂,藩鎮割據,戰事頻仍,魑魅魍魎,肆逆於道。兵戈逼泰安,街鄰皆逃亡,獨溪不捨錦鯉,未去。 是夜,院室倏火。有人入火護溪,言其本鯉中妖,欲取溪命,卻生情愫,遂不忍為之。翌日天明,火勢漸歇,人已不見。

原創不易,如果感覺不錯,希望給個推薦!您的支持是我寫作的最大動力!
版權聲明:
作者:虛無境
博客園出處:http://www.cnblogs.com/xuwujing
CSDN出處:http://blog.csdn.net/qazwsxpcm    
個人博客出處:http://www.panchengming.com


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 給定兩個字元串 s 和 t,判斷它們是否是同構的。 如果 s 中的字元可以被替換得到 t ,那麼這兩個字元串是同構的。 所有出現的字元都必須用另一個字元替換,同時保留字元的順序。兩個字元不能映射到同一個字元上,但字元可以映射自己本身。 示例 1: 輸入: s = "egg", t = "add" 輸 ...
  • 統計所有小於非負整數 n 的質數的數量。 示例: 輸入: 10 輸出: 4 解釋: 小於 10 的質數一共有 4 個, 它們是 2, 3, 5, 7 。 class Solution: def countPrimes(self, n): """ :type n: int :rtype: int "" ...
  • 先來張圖: 一、程式計數器:指向當前線程正在執行的位元組碼指令的地址(或者說行號)。每個線程都有一個自己的計數器。 為什麼指向正在執行的位元組碼指令的地址?因為CPU會切換線程執行,當前線程可能會被掛起,被掛起的時候當前指令可能沒執行完成,待CPU重新調度到該線程時,需要知道當前線程執行到哪了。 二、虛 ...
  • 作為實際java開發經驗還不到一年的我,第一次寫博客,誠惶誠恐,怕把自己的謬誤公之於眾,誤人子弟,不過轉念一想,若是能有同行加以指點評判,將他們的真知灼見描述出來,那這篇文章就算拋轉引玉了。 最近在閱讀《Java編程思想》有關介面的最後一小節中,作者提出了工廠設計模式,用來解決 生成實現某個介面的對 ...
  • 才開通博客沒幾天,不知道寫什麼東西,就把最近在項目中做的東西分享一下,開通博客也可以監督一下自己,技術的路很遙遠,希望能通過寫博客來讓自己走的更遠。 一般在web項目中都需要定義一個全局異常來處理一些業務方面的異常,下麵是自定義異常的一些代碼。 1.自定義一個異常,然後繼承RuntimeExcept ...
  • 線性表的鏈式存儲 鏈式結構存儲密度小,存儲空間利用率低 只能順序存儲(其中指針域用來表明節點間的關係) 插入和刪除操作方便 代碼如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 typedef int ElemType; 4 5 typedef str ...
  • 在MyBatis中MapperProxyFactory,MapperProxy,MapperMethod是三個很重要的類。 弄懂了這3個類你就大概清楚Mapper介面與SQL的映射, 為什麼是介面,沒有實例類也可以完成註入或者調用。 其中MapperMethod可以參考:MapperMethod源碼 ...
  • 用到的: import uuid uuid是128位的全局唯一標識符, 通常用32位的一個字元串的形式來表現 uuid.uuid1() 基於MAC地址,時間戳,隨機數來生成唯一的uuid,可以保證全球範圍內的唯一性 uuid.uuid3() 通過計算一個命名空間和名字的md5散列值來給出一個uuid ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...