鄭苗
摘要:軟件開發(fā)中,最重要的不是后期的編碼,而是前期的設(shè)計(jì),甚至可以毫不夸張地說,一個軟件的好壞就取決于設(shè)計(jì),因?yàn)榍捌诘脑O(shè)計(jì)會直接影響后期的開發(fā)以及維護(hù)。從中,我們就可以知道設(shè)計(jì)是多么重要,這樣一來,理解并學(xué)習(xí)設(shè)計(jì)模式就顯得很有必要了。而在目前市面上出現(xiàn)的多種編程語言中,Java的熱度是最高的。因此該文將通過Java來闡述對目前較流行的幾種設(shè)計(jì)模式的理解與實(shí)現(xiàn)。
關(guān)鍵詞:軟件開發(fā);實(shí)現(xiàn);Java;設(shè)計(jì)模式
中圖分類號:TP393 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2017)32-0115-02
1 概述
總體而言,設(shè)計(jì)模式(Design pattern)是一種設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。它是經(jīng)過前人理解、深挖、設(shè)計(jì)、廣泛使用之后,總結(jié)出來的。其目的是為了讓代碼擁有更強(qiáng)的可讀性、更容易被開發(fā)者理解、可被重復(fù)利用、更可靠。毫無夸張地說,對于開發(fā)者以及系統(tǒng)本身,設(shè)計(jì)模式都是很有利的,設(shè)計(jì)模式,可以使編程更加地充滿樂趣,使代碼更加地規(guī)范。如果把一個系統(tǒng)比作海洋中航行的巨輪的話,那么設(shè)計(jì)模式就是這艘巨輪中的鋼架結(jié)構(gòu)設(shè)計(jì),合理地使用設(shè)計(jì)模式,可以使這艘巨輪更加牢固,能夠抵抗住各種考驗(yàn),解決面臨的問題,也有利于后期的升級改造,會讓它走得更穩(wěn)更遠(yuǎn)。
2 設(shè)計(jì)模式的分類
2.1 創(chuàng)建型模式
原型模式、建造者模式、工廠方法模式、單例模式、抽象工廠模式。
2.2 結(jié)構(gòu)型模式
裝飾器模式、適配器模式、外觀模式、代理模式、享元模式、組合模式、橋接模式。
2.3 行為型模式
解釋器模式、策略模式、模版方法模式、觀察者模式、責(zé)任鏈模式、命令模式、迭代子模式、備忘錄模式、狀態(tài)模式、中介者模式、訪問者模式。
3 設(shè)計(jì)模式的六大原則
3.1 開閉原則
什么叫開閉原則呢?其實(shí)意思就是對修改是關(guān)閉的,但是對擴(kuò)展是開放的。當(dāng)我們的系統(tǒng)在面臨升級,需要對它做一些擴(kuò)展,這個時候,對于之前的那些代碼,我們最好是不要去做修改。用比較專業(yè)的術(shù)語來說就是:想要讓我們的系統(tǒng)更好地升級和維護(hù),擁有更好的擴(kuò)展性,需要我們?nèi)ナ褂贸橄箢惡徒涌凇?/p>
3.2 里氏代換原則
什么叫里氏代換原則呢?面向?qū)ο蟪绦蛟O(shè)計(jì)對于開發(fā)者而言,應(yīng)該是耳熟能詳?shù)?,而這個里氏代換原則就是面向?qū)ο蟪绦蛟O(shè)計(jì)的基本原則之一。簡單來說,里氏代換原則是指,子類可以出現(xiàn)在任何基類可以出現(xiàn)的地方。作為繼承復(fù)用的基礎(chǔ),里氏代換原則中,基類被復(fù)用有一個前提,那就是軟件單位的功能不會因?yàn)樽宇愄鎿Q掉基類的而受到影響,從而,子類也可以基于基類增加新的功能。其實(shí)這個原則也可以說是對上面“開閉原則”的補(bǔ)充?!伴_閉原則”的實(shí)現(xiàn),很重要的一步就是做抽象化處理。而子類與基類之間的繼承關(guān)系也具體實(shí)現(xiàn)了抽象化,因此,換言之,里氏代換原則規(guī)范了實(shí)現(xiàn)抽象化的具體步驟。
3.3 依賴倒轉(zhuǎn)原則
這個原則是作為開閉原則的基礎(chǔ),它的意思是指,當(dāng)我們面向接口編程的時候,我們是需要依賴抽象,但是不依賴具體的。
3.4 接口隔離原則
接口隔離原則是指:使用單個接口不會比使用多個隔離的接口要好。就是松耦合的意思,我們從這兒不難看出,設(shè)計(jì)模式其實(shí)就是作為軟件的設(shè)計(jì)思想,它是從軟件架構(gòu)著手的,目的是為了維護(hù)容易和升級。
3.5 迪米特法則
這個也叫做最少知道原則,為什么叫這個呢? 意思是:實(shí)體之間需要盡可能少的相互作用,這樣就可以使系統(tǒng)各個功能模塊看起來是相對獨(dú)立的,也能便于維護(hù)。
3.6 合成復(fù)用原則
原則是不使用繼承,盡量使用合成/聚合的方式。
4 設(shè)計(jì)模式詳細(xì)實(shí)現(xiàn)
4.1 代理模式(Proxy)
顧名思義,在該種模式下,會有一種代理類的產(chǎn)生,通過該代理類,我們可以擁有原對象的一些功能,比如我們在買火車票的時候有時會去一些代售點(diǎn)而不是直接去火車站,這里的代售點(diǎn)就是代理的意思。
根據(jù)上文的闡述,代理模式就比較容易理解了,我們看下代碼實(shí)現(xiàn):
interface Station {
int saleTicket(); }
class BeijingStation implements Station {
@Override
int saleTicket() {
System.out.println("beijing station can sale tickets!"); } }
class Xiecheng implements Station {
private Station station;
Xiecheng(){
super();
this.station = new Station(); }
@Override
int saleTicket() {
proxyBef();
station.saleTicket();
proxyAft(); }
int proxyAft() {
System.out.println(" proxyafter!"); }
int proxyBef() {
System.out.println("proxybefore !"); } }
代理模式有如下的應(yīng)用場景:
當(dāng)已有方法在使用時需要對之前的方法做一些改進(jìn)時,有兩種處理辦法:endprint
1) 通過修改之前的方法來完成我們的需求。但是這樣做的話,就違反了一個原則,那就是開閉原則。
2) 設(shè)置一個中間代理類,通過這個中間代理類來調(diào)用之前方法,并且,對這個類調(diào)用產(chǎn)生的結(jié)果做控制。
以上第2種方法就是很好地運(yùn)用了代理模式,從中,我們不難看出,代理模式能夠?qū)δ茏龀龈忧逦膭澐?,這對于后期維護(hù)是很有利的。
4.2 觀察者模式( Observer)
這個模式講的是類和類的關(guān)系,但是它跟繼承是沒有關(guān)系的。這種模式其實(shí)是比較容易理解的,它跟RSS訂閱和郵件訂閱的關(guān)系很像,比如,我們閱讀wiki或博客時,RSS圖標(biāo),我們會經(jīng)??吹?,放在這來講就是,當(dāng)你關(guān)注并訂閱某篇文章,后續(xù)如果這篇文章有更新的話,它也會非常及時地通知到你。換言之:一個對象當(dāng)它發(fā)生變化的時候,依賴該對象的其他對象是都會收到相應(yīng)的通知的,而且也會做出相應(yīng)的變化。對象與對象之間是一對多的關(guān)系。如圖1所示。
這些類的作用,我來解釋下:我們的主對象就是MySubject類,MySubject類有2個依賴于它的對象,就是Observer1和Observer2,當(dāng)它發(fā)生變化的時候,依賴于它的Observer1和Observer2也必然會發(fā)生變化。而AbstractSubject類里則定義了對象列表,這些對象列表是需要被監(jiān)控的,可以對其進(jìn)行增加或刪除被監(jiān)控對象的修改,并且當(dāng)主對象發(fā)生變化時,AbstractSubject會告警在其列表中存在的對象。具體代碼如下:
定義Check接口:
interface Watch{
void change();
}
定義實(shí)現(xiàn)類:
class Watch1 implements Watch{
@Override
void change() {
System.out.println("watch1 gets!"); } }
class Watch2 implements Watch{
@Override
void change() {
System.out.println("watch2 gets!"); } }
實(shí)現(xiàn)類和AbstractSubject接口:
interface AbstractSubject{
/*觀察者增加*/
void add(Watch watch);
/*觀察者刪除*/
void delete(Watch watch);
/*所有的觀察者被通知*/
void tellWatchs();
void show();
}
abstract class ASubjectImpl implements AbstractSubject{
List
@Override
void add(Watch watch) {
list.add(watch); }
@Override
void del(Watch watch) {
list.remove(watch); }
@Override
void tellWatchs() {
for(int i=0;i Watch watch = list.get(i); watch.change();} } } class MySub extends ASubjectImpl { @Override void show() { System.out.println("change self!"); tellWatchs(); } } 觀察者模式其實(shí)不難,只是有些抽象,不太容易整體理解,但是根據(jù)關(guān)系圖以及參考我的代碼,整理邏輯梳理一遍,這樣就會比較容易理解了! 5 總結(jié) 設(shè)計(jì)模式的學(xué)習(xí)是一個長期的過程,需要幾個階段的學(xué)習(xí),更要注重理論與實(shí)現(xiàn)的結(jié)合,大量地準(zhǔn)確地將所學(xué)的設(shè)計(jì)模式運(yùn)用到項(xiàng)目中去,充分發(fā)揮設(shè)計(jì)模式的作用,這樣才能體會到它的奧妙之處。 參考文獻(xiàn): [1] 范偉.軟件設(shè)計(jì)模式研究及應(yīng)用[J]. 山東工業(yè)技術(shù), 2015(20). [2] 羅興榮.軟件設(shè)計(jì)模式及其使用[J].數(shù)字技術(shù)與應(yīng)用,2013(4). [3] 蔣繼冬. 簡單工廠模式在面向接口編程中的應(yīng)用[J].電子技術(shù)與軟件工程,2013(20). [4] 劉耀欽.單例模式及其擴(kuò)展在Web開發(fā)中的應(yīng)用分析[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2014(5). [5] 杜增毅. 淺談主要的Java設(shè)計(jì)模式[J].電腦迷,2017(4).