時間過得真快啊,不知不覺又要週末了,借這個週末時間。把《淺談設計模式的學習(下)》補上吧。編程
在《淺談設計模式的學習(中)》中,說到了保持抽象的思惟。接下來講一下第四點,作一個分享,也記錄一下本身的學習歷程。設計模式
四、學習設計模式,就不要把它看的太認真網絡
設計模式是一個編程思想,它不是具體的代碼套路。舉個例子說明一下:tcp
因爲家傳,接觸到了一些中國的傳統武術。當我與那些不懂傳統武術的人交流的時候,他們老是認爲中國的傳統武術都是些套路、花架子,只是用來好看。在他們認爲,兩人打架,別人出拳又不是按照你的固定套路來,因此那些武術套路確定無法用來實戰。實際上是怎麼樣呢?我想說他們太不瞭解中國傳統武術了。其實傳統武術不止套路,套路只是傳統武術的一個練習身體協調等能力的輔助。其主要仍是在思想。好比說,一動而無不動,就是讓你調動全身動力來進行防護反擊。學習傳統武術就是把那些技擊思想練到身上(固然,本人只是偶爾練練,還沒那本事)。設計模式也是,它是一個在某些場景下的編程思想,或者說是思路。並非固定套路。開發場景是多樣的,這就要求你根據必定的思想合理的設計代碼的結構。而不是必定要跟書上介紹的設計模式的代碼結構如出一轍。設計模式是思想層的東西,是抽象的,因此不用怕,它容許你多變靈活的使用,合理便可。不要把它看的太認真(不知道有沒有人也跟我當初那樣,認爲必須寫一個什麼接口,而後怎麼繼承怎麼組合調用纔算是正確的設計模式)ide
好像不管怎麼說,都顯得很抽象。那就再來一個例子,用來跟上一遍文章中的那個責任鏈模式作一下比較來講明:學習
場景:模仿網絡模型,數據包先通過tcp加上協議頭後,再通過http加上http協議頭後最後經過網絡傳輸給對方。this
第一步:幾乎全部的設計模式都須要抽象出接口或者抽象類的,因此咱們抽象出一個產生數據包的接口spa
1 public interface IPackageCreator { 2 3 public String createPackage(); 4 }
第二步:咱們簡單地寫一個實現IPackageCreator接口的具體產生消息體的類:設計
1 public class PackageBodyCreator implements IPackageCreator { 2 3 @Override 4 public String createPackage() { 5 6 return "你們好"; 7 } 8 9 }
第三步:咱們要在產生的消息體上加tcp協議頭,還要再加http協議頭。考慮添加的協議頭可能隨時變化,好比說還須要再包裝一個什麼其餘的協議頭。咱們就用裝飾模式來一個個裝飾。即便後邊需求變了,咱們也能夠自由組合達到咱們想要的功能。全部的裝飾者都須要有一個具體的裝飾對象,因此咱們把此對象抽取到一個抽象裝飾者類中。因爲裝飾者類是對被裝飾者類的功能增強,不該該讓客戶端調用時感受到裝飾先後的差別,因此此抽象類實現了IPackageCreator接口:3d
1 public abstract class AbstractDecorator implements IPackageCreator { 2 3 protected IPackageCreator creator; 4 5 public AbstractDecorator(IPackageCreator c){ 6 this.creator = c; 7 } 8 9 }
第四步:如今咱們能夠寫具體的裝飾者類了,這是用來添加tpc協議頭和http協議頭的兩個裝飾着類:
1 public class PackageTcpCreator extends AbstractDecorator { 2 3 public PackageTcpCreator(IPackageCreator c) { 4 super(c); 5 } 6 7 @Override 8 public String createPackage() { 9 10 return "tcp協議頭:"+this.creator.createPackage(); 11 } 12 13 }
1 public class PackageHttpCreator extends AbstractDecorator{ 2 3 public PackageHttpCreator(IPackageCreator c) { 4 super(c); 5 } 6 7 @Override 8 public String createPackage() { 9 10 return "http協議頭:"+this.creator.createPackage(); 11 } 12 13 }
第五步:接下來看一下客戶端代碼的編寫:
1 public class Main { 2 3 public static void main(String[] args) { 4 IPackageCreator creator = new PackageBodyCreator(); 5 IPackageCreator tcpDecorater= new PackageTcpCreator(creator); 6 IPackageCreator httpDecorater = new PackageHttpCreator(tcpDecorater); 7 System.out.println(httpDecorater.createPackage()); 8 } 9 10 }
整個代碼寫完了。這種模式有沒有很熟悉的感受啊,就跟inputstream套了一層BufferedInputStream,而後再套一層DateInputStream差很少吧。都是裝飾者模式嘛。可是跟《淺談設計模式的學習(中)》中的責任鏈模式比一下呢。都有一條鏈對吧,並且都有接口、抽象類和具體實現。會不會有點混亂呢。可能會有點吧,怎麼個個設計模式都有接口、繼承抽象類啊,不少也會是一個對象有一個另外一個接口的引用屬性。這就由於設計模式的目標就是爲了方便擴展。爲了擴展天然就須要依賴抽象而不是具體對象了。因此不少設計模式都有接口、繼承等關係很正常。若是咱們在學習設計模式時,刻意記住建立一個什麼樣的接口,如何去繼承去實現。那麼咱們會被他們大部分的類似性搞混。對於以上說的責任鏈模式和裝飾模式,咱們只須要理解:裝飾模式是對已對象功能的加強;責任鏈模式是按一個鏈條一次處理任務。具體怎麼應用你還得須要根據應用場景靈活多變。
五、學習設計模式,多讀開源代碼最有效
設計模式原本就是抽象的,學習最好的方式就是例子。雖然講設計模式的書中舉得例子也很多,但例子大都比較「單純」(沒有實際應用場景須要考慮的問題多)。因此學習讀那些優秀的開源代碼是你快速掌握和靈活應用設計模式的最快的方法了。也許剛開始讀源代碼是一個痛苦的過程。但當你開始了慢慢的就能找到一些規律,也就變得容易。萬事開頭難。兩週後的今天你確定比如今開始的你更優秀!