JAVA~~~i love you

          面向?qū)ο笤O(shè)計(jì)之LSP

          ??????前段時(shí)間完成我的畢業(yè)論文,是關(guān)于面向?qū)ο笤O(shè)計(jì)原則和設(shè)計(jì)模式的一些討論,為此重讀了Robert C.Martin的《Aglile Software Development Principles,Patterns and Pratices》這本著作,對(duì)面向?qū)ο笤O(shè)計(jì)有了一個(gè)新的認(rèn)識(shí),在這里和大家分享一下。
          ??????《Agile》一書中提到一系列的面向?qū)ο笤O(shè)計(jì)原則,其中一條是叫作LSP---Liskov替換原則。LSP是Barbara Liskov在她1988年的論文中提出的,其內(nèi)容是:子類必須能夠完全替換掉它的父類。LSP是使OCP成立的條件之一(關(guān)于OCP在以后的文章會(huì)作討論),二者都是面向?qū)ο蟮亩鄳B(tài)和抽象的基礎(chǔ)。
          ??????舉個(gè)例子,當(dāng)我們有一個(gè)Car這個(gè)類

          public ? class ?Car?{
          ????
          ????
          public ? void ?run(){
          ????????System.out.println(
          " I?am?running " );
          ????}
          ????
          ????
          public ? void ?stop(){
          ????????System.out.println(
          " I?am?stop " );
          ????}
          }

          現(xiàn)在,如果有一個(gè)類與Car類有關(guān)系,在面向?qū)ο笾?,類之間的關(guān)系就是組合和繼承。當(dāng)確定這個(gè)類為另外一個(gè)類的使用者、擁有者時(shí)就用組合,譬如Person類使用Car類。使用者的類有一個(gè)特征就是運(yùn)行時(shí)多態(tài)放在它們之間是不管用的,譬如Person可能有一些eat、laugh等公共方法,如果Person是Car的子類,根據(jù)運(yùn)行時(shí)多態(tài)就可以用Car來(lái)替換Person,Car就有得eat這個(gè)方法,顯然是不合邏輯的。
          ??? 如果確定是有一種特殊的Car會(huì)飛的,除了run和stop之外還有一個(gè)fly的方法,現(xiàn)在就是使用繼承的場(chǎng)合。

          public?class?FlyingCar?extends?Car?{

          ????
          public?void?fly(){
          ????????System.out.println(
          "I?am?Fly");
          ????}
          }

          雖然使用了繼承,但是確違反了LSP。因?yàn)镃ar中并沒有fly這個(gè)方法,運(yùn)行時(shí)多態(tài)便被破壞。為了獲得多態(tài)性,將Car重構(gòu)為抽象類,在其中添加一個(gè)抽象的fly方法,多態(tài)性便得以保存。但是這樣做的話就說(shuō)明所有Car的抽象都是會(huì)fly的,這顯然是不合理。為此,應(yīng)該去掉Car中的fly方法,Car就不是抽象類,再由Car這個(gè)抽象類派生出抽象的FlyingCar,里面包含fly的抽象方法。這樣,F(xiàn)lyingCar抽象類和它的派生類就確保遵守了LSP了。
          ??????還有一種做法,將fly方法抽象到一個(gè)Flyable接口中。FlyingCar在繼承Car的同時(shí)實(shí)現(xiàn)Flyable接口,就是說(shuō),F(xiàn)lyingCar的上級(jí)父類就是Car和Flyable,按照LSP是完全可以覆蓋父類的。
          public?interface?Flyable?{

          ????
          void?fly();
          }

          public?class?FlyingCar?extends?Car?implements?Flyable?{

          ????
          public?void?fly(){
          ????????System.out.println(
          "I?am?fly");
          ????}
          }

          使用運(yùn)行時(shí)多態(tài)時(shí)要獲得fly方法必須轉(zhuǎn)型為Flyable接口
          public?class?CarMain?{

          ????
          public?static?void?main(String[]?args)?{
          ????????Car?car
          =new?FlyingCar();
          ????????car.run();
          ????????car.stop();
          ????????((Flyable)car).fly();
          ????}
          }

          LSP是指導(dǎo)使用繼承的準(zhǔn)則。繼承肯定是子類添加父類所不具有的新方法的,此時(shí)若忽略LSP,多態(tài)性便會(huì)在設(shè)計(jì)中消失。所以當(dāng)使用繼承時(shí),為了保證多態(tài)性,就需要遵守LSP多做一些工作了。

          posted on 2006-08-03 00:28 it民工 閱讀(775) 評(píng)論(1)  編輯  收藏 所屬分類: 面向?qū)ο笏枷?/a>

          評(píng)論

          # re: 面向?qū)ο笤O(shè)計(jì)之LSP 2006-08-23 23:58 豪杰

          你的編程好厲害啊,以后就來(lái)請(qǐng)教下你先得,呵呵  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2006年8月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 如皋市| 尤溪县| 来宾市| 准格尔旗| 庐江县| 女性| 恩平市| 肇源县| 武城县| 绵阳市| 龙陵县| 霸州市| 绩溪县| 四平市| 木兰县| 曲阜市| 邵阳市| 宁德市| 成安县| 正定县| 大同县| 色达县| 海盐县| 峨山| 大化| 象州县| 张北县| 茂名市| 新源县| 荣昌县| 治多县| 上栗县| 江口县| 同仁县| 涞水县| 门头沟区| 松潘县| 德阳市| 泸水县| 东乡族自治县| 二手房|