多態(tài)與設(shè)計(jì)模式之我的理解
最近因?yàn)殚_發(fā)一個項(xiàng)目的關(guān)系在研究《Head First設(shè)計(jì)模式》,想從中找到一些靈感,雖然之前也看過,但是每次學(xué)習(xí),都會有新的理解和感悟,非常感謝作者提供了這樣一本讓我受益匪淺的書!面向?qū)ο蟪绦蛟O(shè)計(jì)(注意這里是面向?qū)ο螅皇腔趯ο螅┑囊粋€很重要的設(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)”,指同一個實(shí)體同時具有多種形式。在面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài)。引用Charlie Calverts對多態(tài)的描述——多態(tài)性是允許你將父對象設(shè)置成為和一個或更多的他的子對象相等的技術(shù),賦值之后,父對象就可以根據(jù)當(dāng)前賦值給它的子對象的特性以不同的方式運(yùn)作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。如果一個語言只支持類而不支持多態(tài),只能說明它是基于對象的,而不是面向?qū)ο蟮摹@枚鄳B(tài),程序可以針對”超類型“編程,執(zhí)行時會根據(jù)實(shí)際狀況執(zhí)行到真正的行為,不會被綁死在超類型的行為上。
以下是非多態(tài)和多態(tài)的對比:
例子:假設(shè)有一個類Animal,有兩個子類(Dog與Cat)繼承Animal:
針對實(shí)現(xiàn)編程是這樣做的:
class Animal { class Dog extends Animal{ class Cat extends Animal{ public class AnimalTest { 而”針對接口/超類型編程"做法如下:
在這個例子中,Animal animal = new Dog();表示我定義了一個Animal類型的引用,指向新建的Dog類型的對象。由于Dog是繼承自它的父類Animal,所以Animal類型的引用是可以指向Dog類型的對象的。 在這種方式中,程序在執(zhí)行時會根據(jù)animal的實(shí)際狀況(對應(yīng)哪個子類的賦值)執(zhí)行到真正的行為(哪個子類的方法),不會被綁死在超類型的行為上,這也就是“在運(yùn)行時指定具體實(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、父類 和 繼承父類并覆蓋父類中同一方法的幾個不同子類實(shí)現(xiàn)的. (2)通過將子類對象引用賦值給超類對象引用變量來實(shí)現(xiàn)動態(tài)方法調(diào)用。 (3)java 的這種機(jī)制遵循一個原則:當(dāng)超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調(diào)用誰的成員方法,但是這個被調(diào)用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。 1、如果a是類A的一個引用,那么,a可以指向類A的一個實(shí)例,或者說指向類A的一個子類。 2、如果a是接口A的一個引用,那么,a必須指向?qū)崿F(xiàn)了接口A的一個類的實(shí)例。 |