上次講了設計模式中的建造型模式,此次來談談結構型模式。其實結構型模式與建造型模式有很大的類似之處,有時都是爲了返回一個新構造的對象,而結構型模式的重點在於基於已有的類的組合來構造符合特定要求的新類。下面基於源碼分析一下幾種常見的結構型模式。設計模式
首先說橋接模式,結構型模式中最重要的模式,用於把抽象化與實現化解耦,使得兩者能夠獨立變化,更通俗準確地說就是分別定義高層的接口和具體的實現,使得具體實現修改了,高層接口能夠不變。橋接模式與其餘不少設計模式有着類似之處,我一開始看了一些橋接模式的源碼後感受它與工廠模式沒有什麼區別。其實,橋接模式的思想是純粹的抽象與實現的分離,其餘不少模式中都蘊含着這樣的思想,因此存在一些類似性,而橋接模式是當中最標準的抽象、實現解耦模式。好比要說工廠模式與橋接模式有什麼區別,實質上區別仍是很大的,工廠模式的目的在於建立對象時使用統一的接口而不暴露建立邏輯,而橋接模式的目的如上所說,對不一樣的實現方式用統一的接口進行操做,可見工廠模式能夠看做橋接模式在建立對象時的特例。服務器
如下是橋接模式的通常性源碼:ide
public abstract class Implementor{ 2: public abstract void OperationImp(); 3: } 4: 5: public class ConcreteImplementorA extends Implementor{ 6: public void OperationImp(){ 7: //省略實現... 8: } 9: } 10: 11: public class ConcreteImplementorB extends Implementor{ 12: public void OperationImp(){ 13: //省略實現... 14: } 15: } 16: public abstract class Abstraction{ 17: protected Implementor implementor; 18: public abstract void Operation(); 19: } 20: 21: public class RefinedAbstraction extends Abstraction{ 22: public RefinedAbstraction(Implementor implementor){ 23: this.implementor=implementor; 24: } 25: 26: public void Operation(){ 27: //... 28: implementor.OperationImp();//調用實現化角色實現的操做 29: //... 30: } 31: } 32: 33: public class Client{ 34: public static void main(String[] args){ 35: Abstraction abstraction=new RefinedAbstraction(new ConcreteImplementorA()); 36: abstraction.Operation(); 37: } 38: }
這就很好地說明了橋接模式的內涵,也給出了橋接模式的使用方式。把上述代碼中的 Abstraction 和 Implementor 看做操做系統與不一樣的硬件設備,操做系統爲用戶提供了 read 、 write 這樣的文件操做方式,而這些函數內部封裝了不一樣硬件設備的不一樣驅動函數,這就是橋接模式的典型例子。函數
接着說適配器模式。相對於橋接模式,適配器模式更好理解,它是兩個不兼容的接口之間的橋樑,使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。這樣對用戶來講,能夠用統一的方式調用本來不兼容的類。舉個例子,AudioPlayer 能夠播放 mp3 格式的音頻文件,AdvancedMediaPlayer 能夠播放 vlc 和 mp4 格式的文件,咱們想要讓 AudioPlayer 播放其餘格式的音頻文件。實現方式:源碼分析
public class MediaAdapter implements MediaPlayer { AdvancedMediaPlayer advancedMusicPlayer; public MediaAdapter(String audioType){ if(audioType.equalsIgnoreCase("vlc") ){ advancedMusicPlayer = new VlcPlayer(); } else if (audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer = new Mp4Player(); } } @Override public void play(String audioType, String fileName) { if(audioType.equalsIgnoreCase("vlc")){ advancedMusicPlayer.playVlc(fileName); }else if(audioType.equalsIgnoreCase("mp4")){ advancedMusicPlayer.playMp4(fileName); } } }
public class AudioPlayer implements MediaPlayer { MediaAdapter mediaAdapter; @Override public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("mp3")){ System.out.println("Playing mp3 file. Name: "+ fileName); }
else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){ mediaAdapter = new MediaAdapter(audioType); mediaAdapter.play(audioType, fileName); } else{ System.out.println("Invalid media. "+ audioType + " format not supported"); } } }
這樣就把兩種接口不相同的類用統一的方式封裝,對用戶來講幾個功能均可以用相同的方式調用。適配器模式也體現出結構型模式的特色,即把幾種不一樣的類用特定方式組合到一塊兒,造成符合需求的新類。this
再來講說裝飾器模式,其目的是在不改變類的結構的狀況下,向其動態地添加新的功能。一般咱們要擴展一個類會使用繼承方式,而因爲繼承爲類引入靜態特徵,而且隨着擴展功能的增多,子類會很膨脹,這時能夠考慮裝飾器模式。該模式實現方式是新建一個裝飾類(虛類)並添加被裝飾的類做爲成員,繼承該類並重寫相關功能函數,添加新的功能。以上一篇博客中的 Shape 形狀類爲例(相關源碼見上一篇博客),咱們將把一個形狀裝飾上不一樣的顏色,同時又不改變形狀類。spa
public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }
public class RedShapeDecorator extends ShapeDecorator { public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); } @Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); } private void setRedBorder(Shape decoratedShape){ System.out.println("Border Color: Red"); } }
這樣就在形狀類的基礎上添加了顏色功能。操作系統
最後說說外觀模式,這種模式很是簡單卻十分經常使用,即向客戶端提供了一個客戶端能夠訪問系統的接口,而隱藏了系統的複雜性。簡單來講就是用戶能夠簡潔地調用接口中的功能,而不關注具體實現細節。服務器與客戶端之間的通訊就採用這種模式。依然以 Shape 類爲例,但願統一調用不一樣形狀的 draw 函數。設計
public class ShapeMaker { private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker() { circle = new Circle(); rectangle = new Rectangle(); square = new Square(); } public void drawCircle(){ circle.draw(); } public void drawRectangle(){ rectangle.draw(); } public void drawSquare(){ square.draw(); } }
public class FacadePatternDemo { public static void main(String[] args) { ShapeMaker shapeMaker = new ShapeMaker(); shapeMaker.drawCircle(); shapeMaker.drawRectangle(); shapeMaker.drawSquare(); } }
就是這麼簡單的方式。其與工廠模式的區別在於,工廠模式的目的在於建立,而外觀模式的目的在於使用調用功能。代理
還有一些其餘的結構型模式,好比組合模式用樹形結構表示一組類似對象的層次,過濾器模式用特定要求來過濾一組對象,享元模式用於共享相同的對象來節省資源,代理模式用一個類表明另外一個類的功能來避免直接訪問。細節詳見相關資料,此次就很少說了,下次再來說講行爲型設計模式。