前言 在 "上一篇" 中我們學習了創建型模式的建造者模式和原型模式。本篇則來學習下結構型模式的適配器模式和橋接模式。 適配器模式 簡介 適配器模式是作為兩個不相容的介面之間的橋梁。這種類型的設計模式屬於結構型模式,它結合了兩個獨立介面的功能。 簡單的來說就是通過某個介面將不相容的兩個類進行相容,俗稱 ...
前言
在上一篇中我們學習了創建型模式的建造者模式和原型模式。本篇則來學習下結構型模式的適配器模式和橋接模式。
適配器模式
簡介
適配器模式是作為兩個不相容的介面之間的橋梁。這種類型的設計模式屬於結構型模式,它結合了兩個獨立介面的功能。
簡單的來說就是通過某個介面將不相容的兩個類進行相容,俗稱轉換器。
生活比較典型的例子是電器的電壓,美國的電壓是110V左右, 而中國的電壓普片是220V,如果我們想用美國或日本的電器,則需要一個轉換器,將110V轉換成220V。還有一個很典型例子就是曾經的萬能充,基本可以充各種手機的電池。
這裡我們用一個簡單的示例來進行說明。
某個視頻播放器,只能播放MP4格式的視頻,但是主流的視頻格式除了MP4,還有AVI、RVMB等,這時就有個軟體,格式工廠用於對視頻格式的轉換(適配器),從而進行播放視頻。這時我們就可以使用適配器模式來進行完成該代碼的編寫。
適配器模式主要有兩種類型,一種是類適配器模式,主要通過繼承來實現適配器功能;一種是對象適配器模式,通過組合來實現適配器功能。
首先是類適配器模式,它需要完成一下步驟:
- 建立MP4、AVI、RVMB視頻格式的介面;
- 建立一個視頻播放器的類實現MP4視頻格式的類;
- 編寫一個格式工廠類,將AVI、RVMB等格式的視頻文件轉換成MP4格式的文件。
- 播放這些視頻。
那麼代碼如下:
代碼示例:
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軟體即可。
好了,廢話不在多說,依舊用一個示例來進行說明。
市面上有很多種筆,比如鉛筆、黑色的圓珠筆和紅色的圓珠筆等等, 也有很多種類型的紙,比如考試的卷子用的紙,報紙用的紙等等。一般來說,報紙上的字顏色是黑色的,這裡我們就用黑色的圓珠筆來進行書寫,考試卷子上的打分字顏色是紅色的,這裡我們就用紅色的圓珠筆來進行書寫。筆類和紙類相互獨立,但是在紙上寫字又將它們關聯起來,這裡我們就可以使用橋接模式。
實現步驟如下:
- 定義一個筆類的介面,有寫的這個方法;
- 定義紅筆和黑筆的類,實現筆類的介面;
- 定義一個紙類的抽象類,設置筆的種類,並需要實現被寫的方法;
- 定義卷子紙和新聞紙類,繼承紙類並實現該方法;
- 進行書寫。
代碼示例
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