2. instanceof檢查鏈
這個問題是連續(xù)使用if ... else + instanceof檢查來判斷一個對象的類型,并采取不同的處理邏輯。示例代碼如下:
public void method(Fruit fruit) {
if (fruit instanceof Apple) {
...
}
else if (fruit instanceof Orange) {
...
}
else if .....
}
這不是面向?qū)ο蟮姆椒ǎ耆珱]有利用到多態(tài)的面向?qū)ο筇匦浴N蚁嘈乓粋€合格的程序員是不會寫出這樣的編碼的,這一般是新手程序員,特別是對面向?qū)ο罄斫獠簧羁痰某绦騿T會犯的毛病。改正的方法就是在Fruit類中增加一個方法,并在Apple、Orange等子類中實現(xiàn)此方法:
public abstract class Fruit {
public int m();
}
當(dāng)然,在環(huán)境允許的情況下,盡可能使用protected而不是public來定義這個方法。
現(xiàn)在我們來看一個復(fù)雜一點(diǎn)的,同樣還是instanceof檢查的問題,但這個檢查只涉及了Fruit諸多子類中的一部分,而其他的子類,行為是一致的。這時候我們需要在Fruit中引入一致行為的實現(xiàn):
public abstract class Fruit {
public int m() {
//一般的實現(xiàn)。
...
}
}
而更加復(fù)雜的行為需要對應(yīng)復(fù)雜的設(shè)計,通過對具體水果的抽象,可以發(fā)現(xiàn)這些水果可以抽象為幾個較為一般的類:
public abstract class Fruit {
public int m(){
...
}
}
public class TypeAFruit extends Fruit {
public int m(){
//特定類型的實現(xiàn)。
}
}
public class TypeBFruit extends Fruit {
public int m(){
// 特定類型的實現(xiàn)。
}
}
...
關(guān)于類的繼承層次的問題,有一種說法是“原則上”控制在一定的數(shù)量之內(nèi)。一般來說 這個說法是有道理的(特別是對初學(xué)者,它可以有效的避免“濫繼承”),但不是放之四海皆準(zhǔn)的道理,不要把它教條化。
說到繼承層次,不得不提到抽象層次。我們總是在一定的抽象層次上解決問題,抽象層次決定了你解決問題的實現(xiàn)的復(fù)雜程度。設(shè)計以簡潔為美,不要把設(shè)計復(fù)雜化。但簡潔并不意味著“少”,簡潔的真正涵義是:模型不比模型所表達(dá)的事物更加復(fù)雜,不要把“本來簡單”的東西復(fù)雜化,也不要把本來復(fù)雜的東西簡單化。
我所要表達(dá)的是,設(shè)計應(yīng)該是簡潔的,但不是“簡單”的。“設(shè)計應(yīng)該簡單”的說法,是來自翻譯的問題,還是來自理解的問題?簡單會導(dǎo)向“偷工減料”,而簡潔則要求不要在設(shè)計中加料(特別是廢料)。
一個繼承結(jié)構(gòu)有多少層才是合適的?最上層的類或接口對應(yīng)著“一般概念”,最下層的類一定可以實例化為具體的對象,這中間有多少“層”,就有多少抽象層次。決定抽象層次,也就是決定你的繼承層次的原則有二:
汗,感覺后面有點(diǎn)越扯越遠(yuǎn)了。。。
這個問題是連續(xù)使用if ... else + instanceof檢查來判斷一個對象的類型,并采取不同的處理邏輯。示例代碼如下:
public void method(Fruit fruit) {
if (fruit instanceof Apple) {
...
}
else if (fruit instanceof Orange) {
...
}
else if .....
}
這不是面向?qū)ο蟮姆椒ǎ耆珱]有利用到多態(tài)的面向?qū)ο筇匦浴N蚁嘈乓粋€合格的程序員是不會寫出這樣的編碼的,這一般是新手程序員,特別是對面向?qū)ο罄斫獠簧羁痰某绦騿T會犯的毛病。改正的方法就是在Fruit類中增加一個方法,并在Apple、Orange等子類中實現(xiàn)此方法:
public abstract class Fruit {
public int m();
}
當(dāng)然,在環(huán)境允許的情況下,盡可能使用protected而不是public來定義這個方法。
現(xiàn)在我們來看一個復(fù)雜一點(diǎn)的,同樣還是instanceof檢查的問題,但這個檢查只涉及了Fruit諸多子類中的一部分,而其他的子類,行為是一致的。這時候我們需要在Fruit中引入一致行為的實現(xiàn):
public abstract class Fruit {
public int m() {
//一般的實現(xiàn)。
...
}
}
而更加復(fù)雜的行為需要對應(yīng)復(fù)雜的設(shè)計,通過對具體水果的抽象,可以發(fā)現(xiàn)這些水果可以抽象為幾個較為一般的類:
public abstract class Fruit {
public int m(){
...
}
}
public class TypeAFruit extends Fruit {
public int m(){
//特定類型的實現(xiàn)。
}
}
public class TypeBFruit extends Fruit {
public int m(){
// 特定類型的實現(xiàn)。
}
}
...
關(guān)于類的繼承層次的問題,有一種說法是“原則上”控制在一定的數(shù)量之內(nèi)。一般來說 這個說法是有道理的(特別是對初學(xué)者,它可以有效的避免“濫繼承”),但不是放之四海皆準(zhǔn)的道理,不要把它教條化。
說到繼承層次,不得不提到抽象層次。我們總是在一定的抽象層次上解決問題,抽象層次決定了你解決問題的實現(xiàn)的復(fù)雜程度。設(shè)計以簡潔為美,不要把設(shè)計復(fù)雜化。但簡潔并不意味著“少”,簡潔的真正涵義是:模型不比模型所表達(dá)的事物更加復(fù)雜,不要把“本來簡單”的東西復(fù)雜化,也不要把本來復(fù)雜的東西簡單化。
我所要表達(dá)的是,設(shè)計應(yīng)該是簡潔的,但不是“簡單”的。“設(shè)計應(yīng)該簡單”的說法,是來自翻譯的問題,還是來自理解的問題?簡單會導(dǎo)向“偷工減料”,而簡潔則要求不要在設(shè)計中加料(特別是廢料)。
一個繼承結(jié)構(gòu)有多少層才是合適的?最上層的類或接口對應(yīng)著“一般概念”,最下層的類一定可以實例化為具體的對象,這中間有多少“層”,就有多少抽象層次。決定抽象層次,也就是決定你的繼承層次的原則有二:
- 客戶代碼的需要:客戶代碼是指調(diào)用你的類繼承層次中的某些類的代碼,客戶代碼需要知道某個層次的細(xì)節(jié)。此外需要注意的是,客戶代碼應(yīng)該盡量使用最上層的“一般概念”。
- 重用的需要:在具體的不同類中存在相同代碼的時候,就要考慮有沒有可能進(jìn)行抽象,形成一個用于重用目的的父類。
汗,感覺后面有點(diǎn)越扯越遠(yuǎn)了。。。