1.面向接口編程產(chǎn)生的背景
在一個(gè)面向?qū)ο蟮南到y(tǒng)中,系統(tǒng)的各種功能是由許許多多的不同對(duì)象協(xié)作完成,在這種情況下各個(gè)對(duì)象內(nèi)部是如何實(shí)現(xiàn)自己對(duì)系統(tǒng)設(shè)計(jì)人員來(lái)說(shuō)就不那么重要了.而各個(gè)對(duì)象之間的協(xié)作關(guān)系則成為系統(tǒng)設(shè)計(jì)的關(guān)鍵,在日常工作中,如果別人修改的代碼頻繁的影響到你,表現(xiàn)在某個(gè)模塊的改動(dòng)引起其他模塊的大規(guī)模調(diào)整,說(shuō)明模塊接口沒(méi)有很好的設(shè)計(jì).所有面向接口編程顯得尤為重要.
2.什么是面向接口編程?
面向接口編程就是先把客戶的業(yè)務(wù)邏輯線提取出來(lái),作為接口,業(yè)務(wù)具體實(shí)現(xiàn)通過(guò)該接口的實(shí)現(xiàn)來(lái)完成.當(dāng)客戶需求變化的時(shí)候,只需編寫該業(yè)務(wù)邏輯的新的實(shí)現(xiàn)類,通過(guò)更改配置文件(例如Spring框架)中該接口的實(shí)現(xiàn)類就可以完成需求,不需要修改現(xiàn)有的代碼,減少對(duì)系統(tǒng)的影響
3.面向接口編程的優(yōu)點(diǎn)?
? 1.降低程序的耦合性,能夠最大限度的解耦合
? 2.易于程序的擴(kuò)展
? 3.有利于程序的維護(hù)
4.接口編程在設(shè)計(jì)模式中的體現(xiàn):開閉原則
? 那么是么是開閉原則呢?一句話概括:對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉.
開放封閉原則的簡(jiǎn)單概述:開放-封閉原則是面向?qū)ο笤O(shè)計(jì)的核心所在.遵循這個(gè)原則可以帶來(lái)面向?qū)ο蠹夹g(shù)所聲稱的巨大好處:
可維護(hù)? 可擴(kuò)展? 可復(fù)用? 靈活性好
開發(fā)人員應(yīng)該僅對(duì)程序中呈現(xiàn)出頻繁的變化那部分作出抽象,然而對(duì)于應(yīng)用程序中的每個(gè)部分進(jìn)行刻意的抽象同樣并不是一個(gè)好主意,拒絕不成熟的抽象和抽象本身一樣重要(切記,切記).
? 面向接口將具體邏輯與實(shí)現(xiàn)分開,減少了各個(gè)類之間的相互依賴,當(dāng)各個(gè)類變化時(shí)候,不需要對(duì)已經(jīng)編寫的類進(jìn)行改動(dòng),添加新的實(shí)現(xiàn)類可以了,不用擔(dān)心新改動(dòng)的類對(duì)系統(tǒng)的其他模塊造成影響
5.關(guān)于抽象類的設(shè)計(jì)是如何體現(xiàn)多態(tài)的?
靜態(tài)類型語(yǔ)言通常設(shè)計(jì)為可以“向上轉(zhuǎn)型”。當(dāng)給一個(gè)類變量賦值時(shí),這個(gè)變量的類型既可以使用這個(gè)類本身,也可以使用這個(gè)類的超類。就像看到天上有只麻雀,既可以說(shuō)“一只麻雀在飛”,也可以說(shuō)“一只鳥在飛”,甚至可以說(shuō)成“一只動(dòng)物在飛”。通過(guò)向上轉(zhuǎn)型,對(duì)象的具體類型被隱藏在“超類型”身后。當(dāng)對(duì)象類型之間的耦合關(guān)系被解除之后,這些對(duì)象才能在類型檢查系統(tǒng)的監(jiān)視下相互替換使用,這樣才能看到對(duì)象的多態(tài)性
抽象類的一些作用:
??? 1.向上轉(zhuǎn)型
舉例:
讓麻雀對(duì)象和鴨子對(duì)象的類型都隱藏在抽象類Dird類型之后,隱藏對(duì)象的的具體類型之后,麻雀和鴨子才能被交換使用,這是讓對(duì)象表現(xiàn)出多態(tài)性的必經(jīng)之路
?2.建立一些契約繼承自抽象類的具體類都會(huì)繼承抽象類里的abstract方法,并且要求覆寫它們。這些契約在實(shí)際編程中非常重要,可以幫助編寫可靠性更高的代碼。
比如在命令模式中,各個(gè)子命令類都必須實(shí)現(xiàn)execute方法,才能保證在調(diào)用command.execute的時(shí)候不會(huì)拋出異常。如果讓子命令類OpenTvCommand繼承自抽象類Command:
abstractclass Command{
? publicabstractvoid execute();
}publicclass OpenTvCommand extends Command{
? public OpenTvCommand (){};
? publicvoid execute(){
? ? System.out.println("打開電視機(jī)" );
? }
}
自然有編譯器幫助檢查和保證子命令類OpenTvCommand覆寫了抽象類Command中的execute抽象方法。如果沒(méi)有這樣做,編譯器會(huì)盡可能早地拋出錯(cuò)誤來(lái)提醒正在編寫這段代碼的程序員
總而言之,不關(guān)注對(duì)象的具體類型,而僅僅針對(duì)超類型中的“契約方法”來(lái)編寫程序,可以產(chǎn)生可靠性高的程序,也可以極大地減少子系統(tǒng)實(shí)現(xiàn)之間的相互依賴關(guān)系,這就是面向接口編程
6.使用抽象類還是接口?
?分析:?在使用接口的同時(shí)仍舊可以使用抽象類,不過(guò)這時(shí)抽象類的作用是實(shí)現(xiàn)行為,而不是定義行為.只要實(shí)現(xiàn)行為的類遵從接口定義,即使它改變了父抽象類,也不用改變其它代碼與之交互的方式。特別是對(duì)于公用的實(shí)現(xiàn)代碼,抽象類有它的優(yōu)點(diǎn)。抽象類能夠保證實(shí)現(xiàn)的層次關(guān)系,避免代碼重復(fù)。然而,即使在使用抽象類的場(chǎng)合,也不要忽視通過(guò)接口定義行為模型的原則。從實(shí)踐的角度來(lái)看,如果依賴于抽象類來(lái)定義行為,往往導(dǎo)致過(guò)于復(fù)雜的繼承關(guān)系,而通過(guò)接口定義行為能夠更有效地分離行為與實(shí)現(xiàn),為代碼的維護(hù)和修改帶來(lái)方便。
? 行為模型要通過(guò)接口定義而不是抽象類. 抽象類結(jié)合接口使用,抽象類的作用是實(shí)現(xiàn)行為,而不是定義行為.
采用接口還是抽象類參考一下兩點(diǎn):
????1. 如果要?jiǎng)?chuàng)建不帶任何方法定義和成員變量的基類,那么就應(yīng)該選擇接口而不是抽象類。
????2. 如果知道某個(gè)類應(yīng)該是基類,那么第一個(gè)選擇的應(yīng)該是讓它成為一個(gè)接口,只有在必須要有方法定義和成員? 變量的時(shí)候,才應(yīng)該選擇抽象類。因?yàn)槌橄箢愔性试S存在一個(gè)或多個(gè)被具體實(shí)現(xiàn)的方法,只要方法沒(méi)有被全部? 實(shí)現(xiàn)該類就仍是抽象類。
7.關(guān)于接口特性的一些整理
1. 接口中的方法可以有參數(shù)列表和返回類型,但不能有任何方法體。
2. 接口中可以包含字段,但是會(huì)被隱式的聲明為static和final。
3. 接口中的字段只是被存儲(chǔ)在該接口的靜態(tài)存儲(chǔ)區(qū)域內(nèi),而不屬于該接口。
4. 接口中的方法可以被聲明為public或不聲明,但結(jié)果都會(huì)按照public類型處理。
5. 當(dāng)實(shí)現(xiàn)一個(gè)接口時(shí),需要將被定義的方法聲明為public類型的,否則為默認(rèn)訪問(wèn)類型,Java編譯器不允許這種情況。
6. 如果沒(méi)有實(shí)現(xiàn)接口中所有方法,那么創(chuàng)建的仍然是一個(gè)接口。
7. 擴(kuò)展一個(gè)接口來(lái)生成新的接口應(yīng)使用關(guān)鍵字extends,實(shí)現(xiàn)一個(gè)接口使用implements。