国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

論開閉原則在JAVA程序設(shè)計(jì)中的應(yīng)用

2017-03-06 20:48:31鄭朝霞
電腦知識(shí)與技術(shù) 2016年30期
關(guān)鍵詞:Java語(yǔ)言多態(tài)性

鄭朝霞

摘要:在使用Java語(yǔ)言開發(fā)軟件過(guò)程中,好的軟件產(chǎn)品必須具有可擴(kuò)展性好、可維護(hù)性及可復(fù)用性,也就是軟件系統(tǒng)要符合開閉原則的。該文討論了在軟件開發(fā)中如何引入接口來(lái)實(shí)現(xiàn)多態(tài),從而使軟件系統(tǒng)滿足開閉原則。

關(guān)鍵詞:開閉原則;Java語(yǔ)言;多態(tài)性

中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2016)30-0262-03

1 背景

在學(xué)習(xí)JAVA程序設(shè)計(jì)的過(guò)程中,經(jīng)常會(huì)看到這樣的話語(yǔ):正是由于接口和抽象類的存在才賦予java強(qiáng)大的面向?qū)ο蟮哪芰?。但?duì)于初學(xué)者來(lái)說(shuō),要理解抽象類和接口的語(yǔ)法很容易,要理解抽象類和接口的本質(zhì)作用卻比較難。如果我們結(jié)合面向?qū)ο蟮脑O(shè)計(jì)模式中的開閉原則來(lái)理解接口和抽象類的作用,則會(huì)比較透徹、容易理解。1988年,Bertrand Meyer在他的著作《Object Oriented Software Construction》

中提出了開閉原則(OCP,Open-Closed Principle),開閉原則的描述比較簡(jiǎn)單,具體如下:Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.軟件實(shí)體(類,模塊,方法等等)應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。其中open for extension(對(duì)擴(kuò)展開放)指的是當(dāng)出現(xiàn)新需求的時(shí)候,可以通過(guò)擴(kuò)展現(xiàn)有軟件實(shí)體達(dá)到目的。開閉原則中“open”,是指軟件組件功能的擴(kuò)展是開放的,允許對(duì)其進(jìn)行功能擴(kuò)展。”Close for modification”(對(duì)修改關(guān)閉)指的是不允許對(duì)該實(shí)體做任何修改,“close”是指對(duì)于原有代碼的修改是封閉的,即不應(yīng)該修改原有的代碼。也就是說(shuō),需要執(zhí)行多樣行為的軟件實(shí)體應(yīng)該設(shè)計(jì)成不需要修改就可以實(shí)現(xiàn)各種需求的變化,堅(jiān)持開閉原則可以大大減輕軟件項(xiàng)目維護(hù)的工作量。

開閉原則的核心就是:軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。

實(shí)現(xiàn)開閉原則的關(guān)鍵就在于“抽象”,而不是基于“實(shí)現(xiàn)”來(lái)編程。下面我們來(lái)看看一個(gè)基于“實(shí)現(xiàn)”編程的例子。

假如我們要實(shí)現(xiàn)這樣一個(gè)需求:爸爸喝綠茶。通過(guò)這個(gè)需求,我們分析其中包含兩個(gè)類:爸爸類和綠茶類。兩個(gè)類之間的關(guān)系如下:

用JAVA語(yǔ)言實(shí)現(xiàn)的代碼如下:

public class GreenTea {

private String color;

private String teaName;

public String getColor() {

return color;

}

public void setColor(String color) {

this.color = color;

}

public String getTeaName() {

return teaName;

}

public void setTeaName(String teaName) {

this.teaName = teaName;

}

public String use() {

return "綠茶是未經(jīng)發(fā)酵制成的茶,因此較多地保留了鮮葉的天然物質(zhì).沖泡綠茶時(shí),水溫控制在80℃~90℃左右...";

}

}

class Daddy {

public void drink(GreenTea gTea) {

System.out.println("爸爸喜歡喝" +gTea.getName());

System.out.println(gTea.use());

}

}

public class DrinkTest {

public static void main(String[] args) {

Daddy dad = new Daddy();

GreenTea gt = new GreenTea();

gt.setName(“綠茶”);

gt.setColor(“紅茶”);

System.out.println(“我是”+gt.getName()+”,顏色為:”+gt.getColor);

dad.drink(gt);

}

}

在上述代碼中,我們可以看到,這是基于實(shí)現(xiàn)來(lái)進(jìn)行的編程,Daddy類是進(jìn)行業(yè)務(wù)邏輯處理的,屬于高層模塊,GreenTea類是低層模塊,負(fù)責(zé)基本的原子操作。在這段代碼中,Daddy類依賴GreenTea類,也就是高層模塊依賴低層模塊,我們看看會(huì)帶來(lái)什么樣的問題。

在實(shí)際的軟件開發(fā)中,需求總是在發(fā)生變化,假如需求變成這樣:爸爸因?yàn)槲覆缓?,改喝紅茶了。紅茶的代碼如下:

class BlackTea {

public String use() {

return "紅茶是一種發(fā)酵而成的茶,其沖泡方法更是豐富多彩,玻璃杯沖泡法、瓷杯沖泡法......";

}

}

現(xiàn)在我們就會(huì)發(fā)現(xiàn),必須要修改負(fù)責(zé)業(yè)務(wù)邏輯處理的Daddy類,爸爸才能喝紅茶,如果爸爸的需求不斷發(fā)生變化,我們就得不斷的修改Daddy類,很顯然上述代碼不符合開閉原則。

而在實(shí)際的軟件開發(fā)中,修改業(yè)務(wù)邏輯處理的高層模塊將會(huì)帶來(lái)風(fēng)險(xiǎn),引入錯(cuò)誤,對(duì)于后期的軟件開發(fā)和維護(hù)帶來(lái)很多的問題。

我們必須修改設(shè)計(jì),讓它符合開閉原則。

2 開閉原則的應(yīng)用

上述代碼顯然不符合開閉原則,因?yàn)檫M(jìn)行業(yè)務(wù)邏輯處理的Daddy類和GreenTea類的耦合度太高,需要降低它們之間的耦合度!那么如何才能降低耦合度。

解決該問題的最關(guān)鍵因素在于抽象化,在編輯語(yǔ)言當(dāng)中,系統(tǒng)可以將抽象設(shè)計(jì)定義為較為固定的設(shè)計(jì)方式,利用Java語(yǔ)言,可以定義多個(gè)接口??梢詳U(kuò)展實(shí)現(xiàn)類,而抽象層都不會(huì)改變,這就進(jìn)一步使得開閉原則的第二條得到滿足,對(duì)修改進(jìn)行關(guān)閉。此外,系統(tǒng)的行為可以通過(guò)從抽象層導(dǎo)出多個(gè)新的實(shí)現(xiàn)類而改變。由于系統(tǒng)設(shè)計(jì)是開放的,這與開閉原則的第一條存在著高度的一致性。

在這里我們?cè)O(shè)計(jì)了一個(gè)三層的結(jié)構(gòu),通過(guò)引入接口和抽象類來(lái)實(shí)現(xiàn)開閉原則。第一層是接口ITea,定義了一個(gè)use()方法;第二層是抽象類Tea,實(shí)現(xiàn)了ITea接口;第三層是具體的實(shí)現(xiàn)類,可以擴(kuò)展很多個(gè)。

接口ITea只定義子類應(yīng)該實(shí)現(xiàn)的方法use(),而沒有實(shí)現(xiàn)公有的功能。在ITea接口中只有一個(gè)方法use(),專門進(jìn)行茶的處理, 由所有的實(shí)現(xiàn)類實(shí)現(xiàn)該方法。同時(shí) ITea作為接口應(yīng)該是穩(wěn)定且可靠的,不應(yīng)該經(jīng)常發(fā)生變化,否則接口做為契約的作用就失去了效能。

引入了抽象類Abstrac class Tea,實(shí)現(xiàn)了公有的功能setColor()、getColor()、setName()、getName,但并沒有實(shí)現(xiàn)use()方法,use()針對(duì)抽象茶類進(jìn)行編程,由具體的實(shí)現(xiàn)類分別去實(shí)現(xiàn)各自的use()方法。并通過(guò)構(gòu)造方法由客戶端來(lái)設(shè)置實(shí)例化的具體茶對(duì)象。如果需要增加一種新的茶,如咖啡Coffee,只需要將Coffee也作為Tea的子類,無(wú)須修改現(xiàn)有類庫(kù)的源代碼。

現(xiàn)階段在大部分的軟件在開發(fā)的過(guò)程當(dāng)中,都定義了實(shí)現(xiàn)類的接口,通過(guò)這種接口的定義,只需要改變一個(gè)實(shí)現(xiàn)類就可以實(shí)現(xiàn)所有實(shí)體的轉(zhuǎn)變。

通過(guò)引入接口和抽象類,就可以讓負(fù)責(zé)業(yè)務(wù)邏輯處理的Daddy類依賴抽象類Tea,而不是依賴實(shí)現(xiàn)類GreenTea類、BlackTea類。也就是高層模塊應(yīng)該依賴抽象,而不是具體的實(shí)現(xiàn)。如圖所示,各子類由接口類定義了接口方法,只需要在不同的子類中編寫不同的實(shí)現(xiàn)即可,當(dāng)然也可以擴(kuò)展自有的方法。

修改后的設(shè)計(jì)如下:

修改設(shè)計(jì)后的實(shí)現(xiàn)代碼如下:

這個(gè)是接口ITea,主要定義方法use()

public interface ITea {

public String use();

}

這個(gè)是抽象類Tea,抽象類Tea實(shí)現(xiàn)了接口ITea

public abstract class Tea implements ITea{

private String color;

private String teaName;

public ITea(String teaName, String color) {

this.teaName = teaName;

this.color = color;

}

public String getColor() {

return color;

}

public void setColor(String color) {

this.color = color;

}

public String getTeaName() {

return teaName;

}

public void setTeaName(String teaName) {

this.teaName = teaName;

}

public abstract String use();

}

這個(gè)是實(shí)現(xiàn)類GreenTea,繼承了抽象類Tea, 實(shí)現(xiàn)了use()方法。我們可以擴(kuò)展很多類似的實(shí)現(xiàn)類。

public class GreenTea extends Tea {

public String use() {

return "綠茶是未經(jīng)發(fā)酵制成的茶,因此較多地保留了鮮葉的天然物質(zhì).沖泡綠茶時(shí),水溫控制在80℃~90℃左右...";

}

}

擴(kuò)展的實(shí)現(xiàn)類紅茶類BlackTea,同樣也是繼承了抽象類Tea,實(shí)現(xiàn)了use()方法。我們不需要修改其他的設(shè)計(jì),只需要擴(kuò)展實(shí)現(xiàn)類就可以了。

class BlackTea extends Tea {

public String use() {

return "紅茶是一種發(fā)酵而成的茶,其沖泡方法更是豐富多彩,玻璃杯沖泡法、瓷杯沖泡法......";

}

}

這個(gè)是業(yè)務(wù)邏輯處理類Daddy,依賴于抽象類Tea.

class Daddy {

public void drink(Tea tea) {

System.out.println("爸爸喜歡喝"+tea.getTeaName()+"!");

System.out.println("顏色為:"+tea.getColor()+"!");

System.out.println(tea.use());

}

}

下面的代碼主要為了測(cè)試軟件的功能,是不是實(shí)現(xiàn)了開閉原則。

public class DrinkTest {

public static void main(String[] args) {

Daddy dad = new Daddy();

GreenTea gt = new GreenTea(“綠茶”,”綠色”);

BlackTea bt = new BlackTea(“紅茶”,”褐色”);

dad.drink(gt);

dad.drink(bt);

}

}

上面的程序是利用Java語(yǔ)言的多態(tài)性來(lái)實(shí)現(xiàn)的軟件開閉原則。多態(tài)性是指程序中定義的父類引用變量所指向的對(duì)象和該引用變量所進(jìn)行的方法調(diào)用在代碼編寫時(shí)并不確定,該引用變量所指向的對(duì)象往往都是在程序運(yùn)行的過(guò)程當(dāng)中才決定的,以及該變量的調(diào)用究竟是在哪個(gè)子類當(dāng)中所實(shí)現(xiàn)的,同時(shí)這也必須是要在程序運(yùn)行的過(guò)程當(dāng)中才可以實(shí)現(xiàn)的。這是由于具體的子類是在程序運(yùn)行的過(guò)程當(dāng)中才被決定下來(lái)的,通過(guò)這種方式,源代碼并不需要 經(jīng)過(guò)修改就可以被直接實(shí)現(xiàn),在這個(gè)過(guò)程當(dāng)中調(diào)用的具體方法也會(huì)隨著被改變,同時(shí)程序在運(yùn)行過(guò)程當(dāng)中所綁定的代碼也會(huì)被隨著改變,同時(shí)該程序也可以以多個(gè)狀態(tài)運(yùn)行,這就是所謂的多態(tài)性,正是因?yàn)榫哂卸鄳B(tài)性才導(dǎo)致軟件具有較強(qiáng)的擴(kuò)展性與靈活性。

在Daddy類中,drink(Tea tea)中父類類型(Tea)的引用將指向子類的對(duì)象(GreenTea、BlackTea等等),在程序運(yùn)行的過(guò)程中,根據(jù)指向的不同實(shí)現(xiàn)類,將調(diào)用不同的子類對(duì)象的use()方法。GreenTea、BlackTea等實(shí)現(xiàn)類繼承抽象類Tea,并實(shí)現(xiàn)了Tea的use()方法。由于GreenTea、BlackTea實(shí)現(xiàn)了use()方法,那么父類類型的引用gt在調(diào)用該方法時(shí)將會(huì)調(diào)用子類中重寫的use()方法。

也就是說(shuō),如果爸爸的需求不斷發(fā)生變化,我們不需要修改進(jìn)行業(yè)務(wù)邏輯處理的Daddy類,只需要擴(kuò)展子類。如果爸想喝茉莉花茶,我們就擴(kuò)展一個(gè)JasmineTea類,增加新的子類不影響已存在類的多態(tài)性、繼承性,以及其他特性的運(yùn)行和操作。

很顯然上述代碼體現(xiàn)了JAVA語(yǔ)言的多態(tài)性,軟件設(shè)計(jì)符合開閉原則。

3 結(jié)束語(yǔ)

大多數(shù)的程序設(shè)計(jì)都需要與閉合原則存在一定的一致性,開閉原則也是對(duì)不同模塊進(jìn)行評(píng)價(jià)的基本依據(jù),我們可以利用開閉原則來(lái)判斷系統(tǒng)的擴(kuò)展性與靈活性。

絕大部分的設(shè)計(jì)模式都必須符合開閉原則,在對(duì)每一個(gè)模式進(jìn)行優(yōu)缺點(diǎn)評(píng)價(jià)時(shí)都會(huì)以開閉原則作為一個(gè)重要的評(píng)價(jià)依據(jù),以判斷基于該模式設(shè)計(jì)的系統(tǒng)是否具備良好的靈活性和可擴(kuò)展性。

所以,我們?cè)趯?shí)際的軟件開發(fā)中,需要通過(guò)擴(kuò)展來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯的變化,而不是修改。如果一個(gè)軟件系統(tǒng)符合開閉原則的,那么從軟件工程的角度來(lái)看,它至少具有這樣的好處:可擴(kuò)展性好、可維護(hù)性好。

參考文獻(xiàn);

[1] 薩默維爾.軟件工程[M]. 程成, 譯. 9版.北京: 機(jī)械工業(yè)出版社, 2011.

[2] Metsker S J.Java設(shè)計(jì)模式[M]. 2版.北京: 電子工業(yè)出版社, 2012.

[3] 趙亞娟. 計(jì)算機(jī)軟件JAVA編程特點(diǎn)及其技術(shù)研究[J]. 數(shù)字技術(shù)與應(yīng)用, 2016(1): 113.

[4] 葛萌, 張琳娜, 陳偉. Java多態(tài)性機(jī)制應(yīng)用研究[J]. 攀枝花學(xué)院學(xué)報(bào), 2016(2): 25-28.

[5] 羅詩(shī)敏. 基于MVC的學(xué)生信息管理系統(tǒng)的分析與設(shè)計(jì)[D]. 廣州: 華南理工大學(xué), 2014

猜你喜歡
Java語(yǔ)言多態(tài)性
單核苷酸多態(tài)性與中醫(yī)證候相關(guān)性研究進(jìn)展
基于Android平臺(tái)的健康醫(yī)療APP設(shè)計(jì)與開發(fā)
大學(xué)生創(chuàng)業(yè)平臺(tái)設(shè)計(jì)與實(shí)現(xiàn)
計(jì)算機(jī)軟件開發(fā)中的JAVA編程語(yǔ)言分析
用戶隱私保護(hù)之手機(jī)密碼保險(xiǎn)箱
馬鈴薯cpDNA/mtDNA多態(tài)性的多重PCR檢測(cè)
GlobalFiler~? PCR擴(kuò)增試劑盒驗(yàn)證及其STR遺傳多態(tài)性
蒙古斑在維吾爾族新生兒中分布的多態(tài)性
基于Java語(yǔ)言的手機(jī)軟件開發(fā)技術(shù)分析
CYP3A4*1G基因多態(tài)性及功能的初步探討
娄烦县| 扎兰屯市| 应城市| 惠州市| 昭通市| 阳曲县| 桦南县| 凌海市| 乌苏市| 泽州县| 丽江市| 平罗县| 芦溪县| 梓潼县| 香港| 航空| 沛县| 当涂县| 南部县| 仪陇县| 田东县| 邢台市| 恭城| 镇原县| 财经| 八宿县| 定兴县| 江油市| 集安市| 夹江县| 宁晋县| 景德镇市| 连云港市| 灵川县| 二连浩特市| 包头市| 潼南县| 衢州市| 平邑县| 邛崃市| 平远县|