作為一個開發人員,能寫出一個漂亮可擴展的代碼,絕對是一件令人愉快的事情。那設計模式就是一門必修課!
本文就自己學習設計模式的一點經歷做一個記錄。
本人在讀大學時,為了學習設計模式就買了一本《Java與模式》的數據,書籍有一千多頁很重、而且價格不菲。沒辦法,花那麼多錢買的不看豈不浪費。於是每天早上讀一章,堅持幾個月我終於讀完了。這幾個月真是煎熬啊,幾個月下來,回憶一下似乎自己真得也沒收獲到什麼,很悍然啊。難道是書籍不好嗎還是我讀的不認真?其實在我現在看來都不是。而為什麼讀完了卻什麼也沒收獲到呢?我覺著:第一是因為我當時編碼的經歷不夠豐富、第二沒有理解設計模式的用途和思想。所以學了有點白學。至於編碼經驗這個只能靠自己多練習,沒什麼好說的。這裡就說說我對設計模式學習的一點理解吧
1、學習設計模式,首先要理解設計模式到底是什麼。
曾經我一度認為,一個設計模式就是一個固定結構的代碼,比如觀察者模式,就是在一個被觀察者裡邊維護一個集合,將觀察者放進這個集合裡,一有事件觸發便遍歷集合裡的觀察者調用他們的某個方法。(如果你也這麼理解,那趕快收手吧,否則你會很痛苦的)這麼理解對嗎?至少我現在認為是打錯特錯的。總共有23種設計模式,是不多,但是如果把每個設計模式理解成一個代碼結構的話肯定會很亂,因為有好多設計模式代碼結構很相似,比如代理模式和裝飾者模式,這麼理解只會讓你混亂搞不清楚,你認為呢?。那我們該怎麼理解設計模式呢,個人覺著哈,一個設計模式是針對的一個應用場景,比如代理模式和裝飾模式,代碼結構很相似,但是代理模式的用途是為了添加別的功能,比如spring的aop就是代理模式的一個很好地應用,項目中有很多數據庫操作,但是無論是曾、刪、改操作前都要打開事務,操作後要提交事務,所以采用代理,將這打開和關閉事務統一管理,這就是相當於在增刪改操作前後添加了別的操作;而裝飾模式呢,他是加強和裝飾某一個已有的功能,最經典的應用就是jdk裡的輸入輸出流了,比如BufferedInputStream就是給InputStream加強了基於緩存讀寫數據流的功能。所以這裡我再強調一遍,設計模式是針對不同的應用場景而不是一個代碼結構(千萬不要通過代碼結構去區分不同的設計模式,就像前邊說的代理和裝飾,代碼結構相似,但是應用目的是不同的)。切記其珍惜啊
2、學習設計模式,首先要清楚設計模式能干什麼。
學習設計模式,你需要心裡認可他,但是對於很多像我一樣的一些初學者吧,因為體會不到他的好處,心裡就沒有去認可他,所以也無從踏心的去學習了。設計模式有什麼好處呢?能干什麼呢?在這裡我舉個例子:(希望你看了也能有所感觸)
我們經常要遍歷一個集合,這個集合可能是ArrayList也可能是LinkedList,學過數據結構的都知道這兩個集合的數據結構是不同的,數據結構不同,所以遍歷方式肯定也不同,這樣現實開發中你要記住每一個數據結構的遍歷方式,如果數據結構更多,那豈不是很累啊(相信你會贊同吧)。但是現實中你遍歷集合,因為集合數據結構的不同而采用不同的遍歷方式了嗎?肯定沒有吧,無論是基於數組還是鏈表的集合,我們用一個Iterator搞定,你只需要在意iterator的兩個方法(hasNext()和next())而不必理會集合的內部數據結構。簡單吧,爽嗎,反正我是感覺很爽,這就是設計模式的一個好處。這裡采用的什麼設計模式呢?不知道能想到嗎,工廠方法模式。ArrayList和LinkedList作為工廠生產自己的Iterator,因為只有自己了解自己內部數據結構和遍歷方式。這裡他們創建的迭代器都實現了Iterator接口,我們是針對的接口編程,所以體會不到不同集合創建的迭代器的不同。(現在你是否認可了設計模式啊,是否認識到他是有用的呢,如果因為這篇文章讓你認可了它,真是我的榮幸啊,哈哈)
上邊這個例子可以說是設計模式能夠封裝變化,讓客戶端調用(就是你調用你用設計模式編寫的類的地方,比如main方法裡)不受變化的影響;下邊我再舉個例子,說一下設計模式另一個能干的事------對方便擴展(就是開閉原則)
大家知道開關和燈泡,開關都有一個打開關閉的功能,無論你是聲控開關還是其他各種類型的開關;燈泡都有一個亮和滅的功能,無亂你是白熾燈、閃關燈的。這樣我們可以分別為燈泡和開關提取一個接口,燈泡接口和開關接口,燈泡接口提供亮和滅方法,開關提供開和關方法。代碼如下:
快關接口:
public interface Switch {
public void setLight(Light light);
public void open();
public void close();
}
1 public interface Light {
2
3 public void lightUp();
4
5 public void LightOff();
6 }在這裡我們再提供一個普通的快關實現:
1 public class NormalSwitch implements Switch{
2
3 private Light light;
4
5 public void setLight(Light light){
6 this.light=light;
7 }
8
9 @Override
10 public void open() {
11 light.lightUp();
12 }
13
14 @Override
15 public void close() {
16 light.LightOff();
17 }
18 }這是一個普通的燈泡實現:
public class NormalLight implements Light {
@Override
public void lightUp() {
System.out.println("燈亮了");
}
@Override
public void LightOff() {
System.out.println("燈滅了");
}
}接下來是客戶端的調用了:
public class Main {
public static void main(String[] args) {
Light light = new NormalLight();
Switch swtich= new NormalSwitch();
swtich.setLight(light);
swtich.open();
swtich.close();
}
}接下來說一說這麼做如何有利於擴展了,比如我要換燈泡了,換個高端大氣上檔次的:
1 public class LuxuriousLight implements Light {
2
3 @Override
4 public void lightUp() {
5 System.out.println("燈泡豪華的亮了");
6 }
7
8 @Override
9 public void LightOff() {
10 System.out.println("燈泡驕傲的滅了");
11 }
12
13 }對於客戶端要怎麼變化呢?來吧看一看:
1 public class Main {
2
3 public static void main(String[] args) {
4 Light light = new LuxuriousLight();//NormalLight();
5
6 Switch swtich= new NormalSwitch();
7
8 swtich.setLight(light);
9
10 swtich.open();
11
12 swtich.close();
13 }
14
15 }看,我們之前的普通燈泡沒有收到任何影響吧,如果還有別的客戶端使用了普通的燈泡,我們新添加的奢侈的燈泡絕對不會影響到他們的邏輯。當然有朋友可能會說,客戶端不也是把new NormalLight改成了new LuxuriousLight了嗎,呵呵,這點改動不無妨,主要是我們後邊通過開關關閉點燈的邏輯沒有變化。這無論是應對變化還是可擴展性都是很有幫助的。在這裡不知道你想到了這是什麼設計模式嗎?沒錯,就是橋接模式,簡單吧。
學習設計模式有一點特別特別重要的一點,就是抽象思維,這是整個設計模式的基石,由於時間原因,下次再續。O(∩_∩)O~
作為程序員,身體是一切的根本,注意身體健康,五一快樂哦
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-03/114687p2.htm