摘 要:設(shè)計(jì)模式是從建筑領(lǐng)域引申到計(jì)算機(jī)應(yīng)用領(lǐng)域的,它并不是我們傳統(tǒng)意義上的算法,是要對問題的解決方法過程做一個(gè)設(shè)計(jì),以達(dá)到軟件重構(gòu)。掌握了設(shè)計(jì)模式并正確應(yīng)用會(huì)使軟件結(jié)構(gòu)更清晰、獨(dú)立并且具備較好的可維護(hù)性。
關(guān)鍵詞:設(shè)計(jì)模式應(yīng)用;計(jì)算機(jī)軟件;軟件設(shè)計(jì)
中圖分類號:TP311.5
隨著計(jì)算機(jī)應(yīng)用技術(shù)的發(fā)展以及實(shí)際工作的需要,軟件系統(tǒng)變得功能越來越強(qiáng),系統(tǒng)也越來越復(fù)雜,這樣對于軟件開發(fā)的各個(gè)階段的構(gòu)思與設(shè)計(jì)都帶來了越來越大的挑戰(zhàn)。軟件設(shè)計(jì)階段中,其設(shè)計(jì)模式是極其重要的,一般情況下,設(shè)計(jì)模式是“面向?qū)ο蟆钡摹C嫦驅(qū)ο笫菍栴}的解決抽象成一個(gè)一個(gè)單一的對象,這些對象相互作用,相互關(guān)聯(lián)和交互形成一個(gè)系統(tǒng),克服了面向過程編程的諸多弊端。但是,面向?qū)ο缶幊痰膽?yīng)用必須有正確的設(shè)計(jì)方法為指導(dǎo)。否則,這個(gè)軟件系統(tǒng)就會(huì)暴露很多弊端,例如:軟件過于死板,往往修改一處,導(dǎo)致軟件多處都要修改,靈活性大幅度下降。代碼冗余過多,造成代碼體積龐大,黏度過大。那么為了開發(fā)一個(gè)高效、靈活和可擴(kuò)展性強(qiáng)的就需要應(yīng)用設(shè)計(jì)模式理論。整篇文章我們將以設(shè)計(jì)模式的分類為主線,分別介紹一種有代表性的設(shè)計(jì)模式,然后在將理論與示例相結(jié)合,從實(shí)際開發(fā)的角度說明設(shè)計(jì)模式的應(yīng)用方法。
1 設(shè)計(jì)模式的原則
1.1 開閉原則
開閉原則是設(shè)計(jì)模式幾大原則中的核心。具體是指:一個(gè)好的系統(tǒng)要求在不修改原來代碼的基礎(chǔ)上,通過增加新代碼可以添加新功能,最關(guān)鍵的就是將功能描述抽象化。例如:對于工廠模式,如果我們清楚得知道將來需要添加計(jì)算功能,則我們就可以將運(yùn)算單獨(dú)抽象為一個(gè)類。根據(jù)前面,這個(gè)運(yùn)算類就是不能隨意更改的,但是我們可以更改繼承它的子類,以達(dá)到要求。
1.2 依賴倒轉(zhuǎn)原則
依賴原則要求:要盡量依賴只說明共性,說明特性的描述,不要依賴它們具體的實(shí)例。抽象的東西才是最穩(wěn)定的,我們要依賴這種穩(wěn)定。比如說觀察者模式中有個(gè)通知者,這個(gè)通知者就不能是具體的。如果通知者是具體的,則萬一被占用,就不能通知。這個(gè)通知者應(yīng)該是抽象的,可以由其他人擔(dān)當(dāng)。
1.3 里氏代換原則
這個(gè)具體就是對繼承進(jìn)行了約束,要嚴(yán)格遵守子類就是父類的關(guān)系。在應(yīng)用和分析程序時(shí),要將父類和子類當(dāng)作一個(gè)整體看待。根據(jù)這個(gè)原則,父類出現(xiàn)的地方子類一樣也可以出現(xiàn)。例如,如果魚是一個(gè)類,則鯨魚就不能是它的子類,應(yīng)為鯨魚不像魚,不是卵生。
1.4 單一職能原則
就一個(gè)類而言,引起它發(fā)生變化的原因必須唯一。換句話說,要盡量做到相同的變化原因的職責(zé)歸在一起,因?yàn)橐苍S雖然職責(zé)不同,但這個(gè)原因可能會(huì)引起另外的職責(zé)。比如,在設(shè)計(jì)類時(shí),要爭取單個(gè)類的功能單一化,這樣調(diào)試時(shí)可以快速定位問題所在,同時(shí)在后期添加新功能時(shí)目標(biāo)也明確,不會(huì)模糊不清,影響其它類的輸出結(jié)果。
2 設(shè)計(jì)模式的分類
2.1 創(chuàng)建型設(shè)計(jì)模式
創(chuàng)建型模式就是將具體實(shí)例的過程抽象化。使得一個(gè)系統(tǒng)不再與創(chuàng)建、組合和表示的對象緊密相關(guān)。一個(gè)類創(chuàng)建型模式通過繼承來改變。而一個(gè)對象創(chuàng)建型模式將則將實(shí)例化的工作交給其它的對象完成。
2.1.1 抽象工廠模式
系統(tǒng)中有一組相關(guān)對象,他們共同工作于系統(tǒng)的某一方面。這時(shí)如果想增加系統(tǒng)一種功能。則只需要新定義一組這樣的相關(guān)對象。通過改變創(chuàng)建方法來動(dòng)態(tài)加載。這個(gè)要求要實(shí)現(xiàn)兩個(gè)不同方面的代碼:第一,實(shí)例化抽象工廠方法的子類。第二實(shí)例化相關(guān)抽象子類,模型如下圖:
圖1 抽象模式的框架設(shè)計(jì)
2.2 結(jié)構(gòu)型設(shè)計(jì)模式
結(jié)構(gòu)型模式通過繼承的方式將接口或?qū)崿F(xiàn)組合在一起。它不是講怎樣將兩者進(jìn)行組合,而是給出怎樣將對象組合的方法,達(dá)到實(shí)現(xiàn)新功能的目的。
2.2.1 裝飾模式
在一般的設(shè)計(jì)中,我們規(guī)定了軟件的功能,然后待軟件完成后,很多時(shí)候如果我們想增加新的功能,可能最直接的就是想增加新的變量,新的方法或者新的邏輯,這些新添加的代碼可能會(huì)給核心的軟件行為帶來新的修飾。這就使主類變得紛繁復(fù)雜,破壞已設(shè)計(jì)的好的清晰結(jié)構(gòu),卻只是做一些裝飾的作用。裝飾模式就是為了解決這類問題。它用單獨(dú)的類來存放所有裝飾功能,要對某個(gè)對象進(jìn)行裝飾時(shí),只需讓該對象被裝飾類包含即可。
圖2 裝飾模式的框架設(shè)計(jì)
2.3 行為型設(shè)計(jì)模式
行為型模式改變了你一直關(guān)注控制流的行為,它除了描述對象和類,同時(shí)要描述清它們之間是怎樣交換的。使你不再受復(fù)雜控制流的煩惱,可以簡單的分析對象之間的關(guān)系就行了。
2.3.1 觀察者模式
有時(shí)被稱作發(fā)布/訂閱模式,觀察者模式定義了一種一對多的依賴關(guān)系,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象。當(dāng)主題對象狀態(tài)發(fā)生變化時(shí),會(huì)發(fā)出廣播,這樣所有的觀察者就會(huì)知曉,根據(jù)廣播信息更新自己記錄的信息。它的應(yīng)用場景可以這樣描述,當(dāng)系統(tǒng)中有很多類,而為了需要必須保持各類狀態(tài)同步,此時(shí)我們肯定不希望增加耦合度,因?yàn)檫@樣以后的修改、擴(kuò)展和重用都會(huì)變得特別麻煩。那么,這時(shí)觀察者模式就是很好的選擇。
圖3 觀察者模式的框架設(shè)計(jì)
3 設(shè)計(jì)模式應(yīng)用舉例
以狀態(tài)模式為例,具體說明此種設(shè)計(jì)模式在軟件設(shè)計(jì)時(shí)的應(yīng)用方法。狀態(tài)模式是行為模式的一種,要求狀態(tài)和行為對應(yīng),一個(gè)變化,另一個(gè)也跟著變化。這個(gè)模式應(yīng)用的典型場景就是需要軟件系統(tǒng)內(nèi)部需要狀態(tài)循環(huán)變化,如果用if else或switch語句則會(huì)增加圈復(fù)雜度,用狀態(tài)模式就可以很好的解決問題。
實(shí)現(xiàn)思想概括為:一個(gè)state,包括兩部分;對象+對象內(nèi)部的屬性(屬性接口+具體屬性)一個(gè)對象,要有其屬性,以及其set,get;且設(shè)置好其初始狀態(tài)以及一個(gè)調(diào)用顯示狀態(tài)的方法(里面就是狀態(tài)調(diào)用自身的顯示方法)。
以黑天白天為例,時(shí)間總是在白天和黑天這兩個(gè)狀態(tài)間變化。我們出始化開始狀態(tài)為白天,在白天的屬性接口里有showState()這個(gè)執(zhí)行方法。在白天這個(gè)屬性里包括顯示時(shí)間的對象,實(shí)現(xiàn)方法show()中不僅有相應(yīng)的響應(yīng),同時(shí)設(shè)置下一個(gè)要呈現(xiàn)的屬性-黑天。同樣,黑天屬性也這樣設(shè)置。這樣,兩次調(diào)用方法就會(huì)形成白天與黑天狀態(tài)連帶響應(yīng)的循環(huán)切換。
代碼:
public interface time {
public void show();
}
class showTime
{
time state;
public time getTime() {
return state;
}
public void setTime(time state) {
this.state = state;
}
public showTime()
{
state=new Day(this);
}
public void showState()
{
state.show();
}
}
class Day implements time
{
showTime display;
public Day(showTime display)
{
this. display=display;
}
public void show()
{
System.out.println(\"now is day, you are awaking!\");
display.setTime(new Night(display);
}
}
class Night implements time
{
showTime display;
public Night(showTime display)
{
this. display=display;
}
public void show()
{
System.out.println(\"now is night,you are sleeping!\");
light.setColor(new Day(display));
}
}
public class CarLight {
public static void main(String[] args) {
showTime time=new showTime();
//初始調(diào)用為白天
time.showState();
//再調(diào)用為黑天
time.showState();
//不斷調(diào)用,不斷循環(huán).
}
}
這樣就可避免不斷的if else判斷,并且程序結(jié)構(gòu)清晰,意義明了。
4 結(jié)束語
每一種設(shè)計(jì)模式都有它自己產(chǎn)生的背景,所以它們大部分專一的解決一類問題。同時(shí),設(shè)計(jì)模式并不是用了一定會(huì)好,關(guān)鍵是用的得當(dāng),要充分掌握它的意圖,在實(shí)際中充分切合它的應(yīng)用背景,否則會(huì)選擇不當(dāng),反而造成相反的結(jié)果。
參考文獻(xiàn):
[1]童立,馬遠(yuǎn)良.設(shè)計(jì)模式在基于組件的框架設(shè)計(jì)中的應(yīng)用[J].計(jì)算機(jī)工程與應(yīng)用,2012(17).
[2]林舒萍,羅鍵.設(shè)計(jì)模式的應(yīng)用研究[J].計(jì)算機(jī)工程與設(shè)計(jì),2005(11).
作者簡介:秦延鋒(1995.05-),男,壯族,廣西南寧人,本科在讀,主要從事電子商務(wù)管理;田濤(1979.02-),男,陜西渭南人,副教授,研究生,主要從事軟件開發(fā)設(shè)計(jì)。
作者單位:廣西民族大學(xué),南寧 530006