<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 100  文章 - 50  trackbacks - 0
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    收藏夾

    我收藏的一些文章!

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

     很多人有過這樣的疑問:為什么有的地方必須使用接口而不是抽象類,而在另一些地方,又必須使用抽象類而不是接口呢?或者說,在考慮Java類的一般化問題時(shí),很多人會(huì)在接口和抽象類之間猶豫不決,甚至隨便選擇一種。

      實(shí)際上接口和抽象類的選擇不是隨心所欲的。 要理解接口和抽象類的選擇原則,有兩個(gè)概念很重要:對(duì)象的行為和對(duì)象的實(shí)現(xiàn)。如果一個(gè)實(shí)體可以有多種實(shí)現(xiàn)方式,則在設(shè)計(jì)實(shí)體行為的描述方式時(shí),應(yīng)當(dāng)達(dá)到這樣一個(gè)目標(biāo):在使用實(shí)體的時(shí)候,無需詳細(xì)了解實(shí)體行為的實(shí)現(xiàn)方式。也就是說,要把對(duì)象的行為和對(duì)象的實(shí)現(xiàn)分離開來。既然Java的接口和抽象類都可以定義不提供具體實(shí)現(xiàn)的方法,在分離對(duì)象的行為和對(duì)象的實(shí)現(xiàn)時(shí),到底應(yīng)該使用接口還是使用抽象類呢?

    通過抽象類建立行為模型

      在接口和抽象類的選擇上,必須遵守這樣一個(gè)原則:行為模型應(yīng)該總是通過接口而不是抽象類定義。為了說明其原因,下面試著通過抽象類建立行為模型,看看會(huì)出現(xiàn)什么問題。

      假設(shè)要為銷售部門設(shè)計(jì)一個(gè)軟件,這個(gè)軟件包含一個(gè)“發(fā)動(dòng)機(jī)”(Motor)實(shí)體。顯然無法在發(fā)動(dòng)機(jī)對(duì)象中詳細(xì)地描述發(fā)動(dòng)機(jī)的方方面面,只能描述某些對(duì)當(dāng)前軟件來說重要的特征。至于發(fā)動(dòng)機(jī)的哪些特征是重要的,則要與用戶(銷售部門)交流才能確定。

      銷售部門的人要求每一個(gè)發(fā)動(dòng)機(jī)都有一個(gè)稱為馬力的參數(shù)。對(duì)于他們來說,這是惟一值得關(guān)心的參數(shù)。基于這一判斷,可以把發(fā)動(dòng)機(jī)的行為定義為以下行為。

      行為1:查詢發(fā)動(dòng)機(jī)的馬力,發(fā)動(dòng)機(jī)將返回一個(gè)表示馬力的整數(shù)。

      雖然現(xiàn)在還不清楚發(fā)動(dòng)機(jī)如何取得馬力這個(gè)參數(shù),但可以肯定發(fā)動(dòng)機(jī)一定支持這個(gè)行為,而且這是所有發(fā)動(dòng)機(jī)惟一值得關(guān)注的行為特征。這個(gè)行為特征既可以用接口定義,也可以用抽象類定義。為了說明用抽象類定義可能出現(xiàn)的問題,下面用抽象類建立發(fā)動(dòng)機(jī)的行為模型,并用Java方法描述行為1,代碼如下:

    public abstract Motor{
                abstract public int getHorsepower();
                }

      在Motor抽象類的基礎(chǔ)上構(gòu)造出多種具體實(shí)現(xiàn),例如A型發(fā)動(dòng)機(jī)、B型發(fā)動(dòng)機(jī)等,再加上系統(tǒng)的其它部分,最后得到1.0版的軟件并交付使用。一段時(shí)間過去了,現(xiàn)在要設(shè)計(jì)2.0版的軟件。在評(píng)估2.0版軟件需求的過程中,發(fā)現(xiàn)一小部分發(fā)動(dòng)機(jī)是電池驅(qū)動(dòng)的,而電池需要一定的充電時(shí)間。銷售部門的人希望能夠通過計(jì)算機(jī)查閱充電時(shí)間。根據(jù)這一要求定義一個(gè)新的行為,如圖1所示。

      行為2:查詢電驅(qū)動(dòng)發(fā)動(dòng)機(jī)的充電時(shí)間,發(fā)動(dòng)機(jī)將返回一個(gè)表示充電時(shí)間的整數(shù)。

      用Java方法來描述這個(gè)行為,代碼如下:

    public abstract BatteryPoweredMotor extends Motor{
                abstract public int getTimeToRecharge();
                }

      在銷售部門的軟件中,電驅(qū)動(dòng)發(fā)動(dòng)機(jī)也以類的形式實(shí)現(xiàn),但這些類從BatteryPoweredMotor而不是Motor派生。這些改動(dòng)加入到2.0版軟件之后,銷售部門很滿意。隨著業(yè)務(wù)的不斷發(fā)展,不久之后光驅(qū)動(dòng)的發(fā)動(dòng)機(jī)出現(xiàn)了。銷售部門要求光驅(qū)動(dòng)發(fā)動(dòng)機(jī)需要一定光能才能運(yùn)轉(zhuǎn),光能以流明(Lumen)度量。這個(gè)信息對(duì)客戶很重要,因?yàn)橄掠昊蚨嘣频奶鞖饫铮承┕怛?qū)動(dòng)發(fā)動(dòng)機(jī)可能無法運(yùn)轉(zhuǎn)。銷售部門要求為軟件增加對(duì)光驅(qū)動(dòng)發(fā)動(dòng)機(jī)的支持,所以要定義一個(gè)新的行為。

      行為3:查詢光驅(qū)動(dòng)發(fā)動(dòng)機(jī)能夠正常運(yùn)轉(zhuǎn)所需要的最小流明數(shù),發(fā)動(dòng)機(jī)返回一個(gè)整數(shù)。

      再定義一個(gè)抽象類并把行為3轉(zhuǎn)換成Java方法,代碼如下:

    public abstract SolarPoweredMotor extends Motor{
                abstract public int getLumensToOperate();
                }

      如圖1所示,SolarPoweredMotor和BatteryPoweredMotor都從Motor抽象類派生。在整個(gè)軟件中,90%以上的代碼以相同的方式對(duì)待所有的發(fā)動(dòng)機(jī)。偶爾需要檢查一下發(fā)動(dòng)機(jī)是光驅(qū)動(dòng)還是電驅(qū)動(dòng),使用instanceof實(shí)現(xiàn),代碼如下:

    if (instanceof SolarPoweredMotor){...}
                if (instanceof BatteryPoweredMotor){...}

      無論是哪種發(fā)動(dòng)機(jī),馬力這個(gè)參數(shù)都很重要,所以在所有派生的抽象類(SolarPoweredMotor和BatteryPoweredMotor)中,getHorsepower()方法都有效。

      現(xiàn)在銷售部門又有了一種新的發(fā)動(dòng)機(jī),它是一種既有電驅(qū)動(dòng)又有光驅(qū)動(dòng)的雙重驅(qū)動(dòng)發(fā)動(dòng)機(jī)。光驅(qū)動(dòng)和電驅(qū)動(dòng)的行為本身沒有變化,但新的發(fā)動(dòng)機(jī)同時(shí)支持兩種行為。在考慮如何定義新型的光電驅(qū)動(dòng)發(fā)動(dòng)機(jī)時(shí),接口和抽象類的差別開始顯示出來了。新的目標(biāo)是在增加新型發(fā)動(dòng)機(jī)的前提下盡量少改動(dòng)代碼。因?yàn)榕c光驅(qū)動(dòng)發(fā)動(dòng)機(jī)、電驅(qū)動(dòng)發(fā)動(dòng)機(jī)有關(guān)的代碼已經(jīng)過全面的測試,不存在已知的Bug。為了增加光電驅(qū)動(dòng)發(fā)動(dòng)機(jī),要定義一個(gè)新的SolarBatteryPowered抽象類。如果讓SolarBatteryPowered從Motor抽象類派生,SolarBatteryPowered將不支持針對(duì)光驅(qū)動(dòng)發(fā)動(dòng)機(jī)和電驅(qū)動(dòng)發(fā)動(dòng)機(jī)的instanceof操作。也就是說,如果查詢一個(gè)光電驅(qū)動(dòng)的發(fā)動(dòng)機(jī)是光驅(qū)動(dòng)的,還是電驅(qū)動(dòng)的,得到的答案是:都不是。

      如果讓SolarBatteryPowered從SolarPoweredMotor(或BatteryPoweredMotor)抽象類派生,類似的問題也會(huì)出現(xiàn),SolarBatteryPowered將不支持針對(duì)BatteryPoweredMotor(或SolarPoweredMotor)的instanceof操作。從行為上看,光電驅(qū)動(dòng)的發(fā)動(dòng)機(jī)必須同時(shí)從兩個(gè)抽象類派生,但Java語言不允許多重繼承。之所以會(huì)出現(xiàn)這個(gè)問題,根本的原因在于使用抽象類不僅意味著定義特定的行為,而且意味著定義實(shí)現(xiàn)的模式。也就是說,應(yīng)該定義一個(gè)發(fā)動(dòng)機(jī)如何獲得行為的模型,而不僅僅是聲明發(fā)動(dòng)機(jī)具有某一個(gè)行為。

    通過接口建立行為模型

      如果用接口來建立行為模型,就可以避免隱含地規(guī)定實(shí)現(xiàn)模式。例如,前面的幾個(gè)行為改用接口定義如下。

      行為1:

    public interface Motor(){
                public int getHorsepower();
                }

    行為2:

    public interface BatteryPoweredMotor extends Motor(){
                public int getTimeToRecharge();
                }

    行為3:

    public interface SolarPoweredMotor extends Motor{
                abstract public int getLumensToOperate();
                }

      現(xiàn)在光電驅(qū)動(dòng)的發(fā)動(dòng)機(jī)可以描述為:

    public DualPoweredMotor implements SolarPoweredMotor, BatteryPoweredMotor{}

      DualPoweredMotor只繼承行為定義,而不是行為的實(shí)現(xiàn)模式,如圖2所示。

      在使用接口的同時(shí)仍舊可以使用抽象類,不過這時(shí)抽象類的作用是實(shí)現(xiàn)行為,而不是定義行為。只要實(shí)現(xiàn)行為的類遵從接口定義,即使它改變了父抽象類,也不用改變其它代碼與之交互的方式。特別是對(duì)于公用的實(shí)現(xiàn)代碼,抽象類有它的優(yōu)點(diǎn)。抽象類能夠保證實(shí)現(xiàn)的層次關(guān)系,避免代碼重復(fù)。然而,即使在使用抽象類的場合,也不要忽視通過接口定義行為模型的原則。從實(shí)踐的角度來看,如果依賴于抽象類來定義行為,往往導(dǎo)致過于復(fù)雜的繼承關(guān)系,而通過接口定義行為能夠更有效地分離行為與實(shí)現(xiàn),為代碼的維護(hù)和修改帶來方便。

    posted on 2007-09-06 10:54 fly 閱讀(124) 評(píng)論(0)  編輯  收藏 所屬分類: java學(xué)習(xí)
    主站蜘蛛池模板: 国产自产拍精品视频免费看| xxxxwww免费| 亚洲综合无码无在线观看| 亚洲AV无码不卡在线播放| 免费大学生国产在线观看p| 无码乱肉视频免费大全合集 | 亚洲av午夜国产精品无码中文字| 久久精品国产亚洲AV网站| 亚洲国产一成久久精品国产成人综合 | 最新国产精品亚洲| 日韩精品亚洲人成在线观看| 国产亚洲情侣一区二区无码AV | 国产亚洲精品美女| 亚洲狠狠婷婷综合久久| 亚洲成AⅤ人影院在线观看| 中文字幕无码免费久久| 一级黄色免费毛片| 精品在线免费视频| 亚洲午夜福利在线观看| 免费大片在线观看网站| 国产成人免费片在线观看| 免费毛片在线看片免费丝瓜视频 | 在线视频免费观看www动漫| 国产美女视频免费观看的网站| 亚洲av色香蕉一区二区三区蜜桃| 亚洲国产亚洲综合在线尤物| 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 成人免费乱码大片A毛片| 青青草国产免费国产是公开| 久久久久亚洲精品无码网址色欲| 亚洲综合一区国产精品| 亚洲精品国产精品国自产网站| 国产亚洲视频在线播放| 亚洲国产精品丝袜在线观看| 亚洲国产精品日韩| 国产亚洲精久久久久久无码AV | 久爱免费观看在线网站| 另类图片亚洲校园小说区| 亚洲Av无码国产一区二区| 综合一区自拍亚洲综合图区| 校园亚洲春色另类小说合集|