qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          多態(tài)與設(shè)計(jì)模式之我的理解

          最近因?yàn)殚_發(fā)一個(gè)項(xiàng)目的關(guān)系在研究《Head First設(shè)計(jì)模式》,想從中找到一些靈感,雖然之前也看過,但是每次學(xué)習(xí),都會有新的理解和感悟,非常感謝作者提供了這樣一本讓我受益匪淺的書!

            面向?qū)ο蟪绦蛟O(shè)計(jì)(注意這里是面向?qū)ο螅皇腔趯ο螅┑囊粋€(gè)很重要的設(shè)計(jì)原則就是:針對接口編程,而不是針對實(shí)現(xiàn)編程!可就是這樣一句句很淺顯的話,確包含了很多面向?qū)ο蟮闹R在里面!

            “什么是針對接口編程呢?”,“針對接口編程的真正意思是”針對超類型編程“。所以這里的”接口“就不再僅僅指的是java中的interface,還包括了抽象類,”超類型“在這里就是指”interface“和”abstract“類,當(dāng)然不包括普通用于繼承的類,因?yàn)槠胀ǖ念愲m然可以繼承但是無法實(shí)現(xiàn)”多態(tài)“。而”多態(tài)“,正是”針對接口編程“的關(guān)鍵之所在!

            ”什么是多態(tài)呢?“,多態(tài)(Polymorphism)按字面的意思就是“多種狀態(tài)”,指同一個(gè)實(shí)體同時(shí)具有多種形式。在面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài)。引用Charlie Calverts對多態(tài)的描述——多態(tài)性是允許你將父對象設(shè)置成為和一個(gè)或更多的他的子對象相等的技術(shù),賦值之后,父對象就可以根據(jù)當(dāng)前賦值給它的子對象的特性以不同的方式運(yùn)作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。如果一個(gè)語言只支持類而不支持多態(tài),只能說明它是基于對象的,而不是面向?qū)ο蟮摹@枚鄳B(tài),程序可以針對”超類型“編程,執(zhí)行時(shí)會根據(jù)實(shí)際狀況執(zhí)行到真正的行為,不會被綁死在超類型的行為上。

            以下是非多態(tài)和多態(tài)的對比:

            例子:假設(shè)有一個(gè)類Animal,有兩個(gè)子類(Dog與Cat)繼承Animal:

            針對實(shí)現(xiàn)編程是這樣做的:

          class Animal {
          String name;
          String sex;

          public void Display()
          {
            System.out.println("name =" + name + "sex =" + sex);
          }
          public void Sound()
          {
            System.out.println("make sound!");
          }
          }

          class Dog extends Animal{
          public void Sound()
          {
            System.out.println("wang...wang...wang...");
          }
          }

          class Cat extends Animal{
          public void Sound()
          {
            System.out.println("miao...miao...miao...");
          }
          }

          public class AnimalTest {
          public static void main(String[] args)
          {
            Dog dog = new Dog();
            dog.Sound();
           
            Cat cat = new Cat();
            cat.Sound();
          }
          }




          在上面這種針對實(shí)現(xiàn)的做法中,dog的行為來自Animal超類的具體實(shí)現(xiàn),或是重載后的Sound方法,這種依賴于”實(shí)現(xiàn)“的做法會被”實(shí)現(xiàn)“綁得死死的,沒辦法更改dog行為,除非在Dog中寫更多的代碼!

            而”針對接口/超類型編程"做法如下:

          class Animal {
          String name;
          String sex;

          public void Display()
          {
            System.out.println("name =" + name + "sex =" + sex);
          }
          public void Sound()
          {
            System.out.println("make sound!");
          }
          }

          class Dog extends Animal{
          public void Sound()
          {
            System.out.println("wang...wang...wang...");
          }
          }

          class Cat extends Animal{
          public void Sound()
          {
            System.out.println("miao...miao...miao...");
          }
          }

          public class AnimalTest {
          public static void main(String[] args)
          {
            Animal animal = new Dog();
            animal.Sound();
           
            animal = new Cat();
            animal.Sound();
          }
          }

           

            在這個(gè)例子中,Animal animal = new Dog();表示我定義了一個(gè)Animal類型的引用,指向新建的Dog類型的對象。由于Dog是繼承自它的父類Animal,所以Animal類型的引用是可以指向Dog類型的對象的。

            在這種方式中,程序在執(zhí)行時(shí)會根據(jù)animal的實(shí)際狀況(對應(yīng)哪個(gè)子類的賦值)執(zhí)行到真正的行為(哪個(gè)子類的方法),不會被綁死在超類型的行為上,這也就是“在運(yùn)行時(shí)指定具體實(shí)現(xiàn)的對象”,這也是多態(tài)的宗旨!當(dāng)然“多態(tài)”的真正含義并不僅僅限于此,而“針對接口編程”正是利用了面向?qū)ο蟮倪@種“多態(tài)”特征來達(dá)到其“接口和具體實(shí)現(xiàn)分離“這一目的的!

            多態(tài)總結(jié):

            (1)多態(tài)是通過:

            1、接口 和 實(shí)現(xiàn)接口并覆蓋接口中同一方法的幾不同的類體現(xiàn)的

            2、父類 和 繼承父類并覆蓋父類中同一方法的幾個(gè)不同子類實(shí)現(xiàn)的.

            (2)通過將子類對象引用賦值給超類對象引用變量來實(shí)現(xiàn)動態(tài)方法調(diào)用。

            (3)java 的這種機(jī)制遵循一個(gè)原則:當(dāng)超類對象引用變量引用子類對象時(shí),被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法,但是這個(gè)被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。

            1、如果a是類A的一個(gè)引用,那么,a可以指向類A的一個(gè)實(shí)例,或者說指向類A的一個(gè)子類。

            2、如果a是接口A的一個(gè)引用,那么,a必須指向?qū)崿F(xiàn)了接口A的一個(gè)類的實(shí)例。

          posted on 2013-01-19 12:52 順其自然EVO 閱讀(519) 評論(0)  編輯  收藏


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


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

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 霞浦县| 绵竹市| 怀柔区| 平原县| 阿合奇县| 施秉县| 阜阳市| 巴青县| 科尔| 彩票| 石家庄市| 桂东县| 合水县| 莫力| 乌什县| 博乐市| 邛崃市| 商丘市| 贵溪市| 宁德市| 民丰县| 合作市| 蒙自县| 峡江县| 平定县| 西林县| 静安区| 元谋县| 丰镇市| 色达县| 于都县| 柳江县| 呼图壁县| 响水县| 泸溪县| 阆中市| 温宿县| 隆林| 高邑县| 成安县| 朔州市|