天天看小說

第179章

大B:“遊戲中會出現(xiàn)各種鴨子,一邊遊戲戲水,一邊呱呱叫,我們設(shè)計(jì)了一個(gè)鴨子超類(Duck),並讓各種鴨子繼承此類。”

Java代碼

PublicabstractclassDuck{

voidquack();//呱呱叫

voidswin();//游泳

abstractvoiddisplay();//鴨子外觀不同,所以是抽象的

//other

}

PublicclassMallardDuckextendsDuck{

Publicvoiddisplay(){

//外觀是綠頭

}

}

PublicclassRedheadDuckextendsDuck{

Publicvoiddisplay(){

//外觀是紅頭

}

}

//otherextends

publicabstractclassDuck{

voidquack();//呱呱叫

voidswin();//游泳

abstractvoiddisplay();//鴨子外觀不同,所以是抽象的

//other

}

publicclassMallardDuckextendsDuck{

publicvoiddisplay(){

//外觀是綠頭

}

}

publicclassRedheadDuckextendsDuck{

publicvoiddisplay(){

//外觀是紅頭

}

}

//otherextends

大B:“現(xiàn)在多了個(gè)主意,要讓鴨子能飛,那麼你可能想到只要在Duck類中加上fly()方法,然後讓所有的鴨子都來繼承這個(gè)方法。”

Java代碼

PublicabstractclassDuck{

Voidquack();//呱呱叫

Voidswin();//游泳

abstractvoiddisplay();//鴨子外觀不同,所以是抽象的

fly();//剛加的會飛的方法,所有的子類都會繼承

//other

}

publicabstractclassDuck{

voidquack();//呱呱叫

voidswin();//游泳

abstractvoiddisplay();//鴨子外觀不同,所以是抽象的

fly();//剛加的會飛的方法,所有的子類都會繼承

//other

}

大B:“但是,可怕的問題就出來了:‘塑料橡皮鴨子’也會飛了,忽略了一件事,並非所有的鴨子都會飛。能想到繼承,把橡皮鴨子類中的fly()方法覆蓋掉,什麼也不做。可是,如果以後要加入木頭鴨子,不會飛也不會叫,你又想到了,把fly()從超類中取出來,做一個(gè)Flyable()接口,同樣的方式,設(shè)計(jì)一個(gè)會叫的接口Quackable()。”

小A:“但是你沒發(fā)現(xiàn)這麼一來重複的代碼會很多嗎?”

大B:“現(xiàn)在我們知道使用繼承並不能很好的解決問題,因爲(wèi)鴨子的行爲(wèi)在子類裡不斷的改變,讓所有的子類都有這些行爲(wèi)是不恰當(dāng)?shù)摹!?

第一個(gè)設(shè)計(jì)原則:

找出應(yīng)用中可能需要變化之處,把它獨(dú)立出來,不要和那些不需要變化的代碼混在一起。現(xiàn)在知道Duck()類裡的fly()和quack()會隨著鴨子的不同而改變,我們把它從Duck()類裡取出來,寫2個(gè)接口:

代碼:

publicinterfaceFlyBehavior{

publicvoidfly();//飛行行爲(wèi)必須實(shí)現(xiàn)的接口

}

publicinterfaceQuackBehavior{

publicvoidquack();//叫行爲(wèi)必須實(shí)現(xiàn)的接口

}publicinterfaceFlyBehavior{publicvoidfly();//飛行行爲(wèi)必須實(shí)現(xiàn)的接口

}

publicinterfaceQuackBehavior{

publicvoidquack();//叫行爲(wèi)必須實(shí)現(xiàn)的接口

}

這樣的設(shè)計(jì)可以讓這2個(gè)動作行爲(wèi)與鴨子類無關(guān),可以被其他的對象複用,也可以新增加一些行爲(wèi)。

第二個(gè)設(shè)計(jì)原則:

針對接口編程,而不是針對實(shí)現(xiàn)編程。

現(xiàn)在來整合下鴨子的行爲(wèi):

代碼:

1、Duck()抽象類

publicabstractclassDuck{

//爲(wèi)行爲(wèi)接口類型聲明2個(gè)引用變量,所有的鴨子子類都繼承它們

FlyBehaviorflyBehavior;

QuackBehaviorquackBehavior;

publicDuck(){

}

//設(shè)定鴨子的行爲(wèi),而不是在鴨子的構(gòu)造器內(nèi)實(shí)例化

publicvoidsetFlyBehavior(FlyBehaviorfb){

flyBehavior=fb;

}

publicvoidsetQuackBehavior(QuackBehaviorqb){

quackBehavior=qb;

}

abstractvoiddisplay();//抽象外觀方法

publicvoidperformFly(){

flyBehavior.fly();//委託給會飛的行爲(wèi)類

}

publicvoidperformQuack(){

quackBehavior.quack();//委託給會叫的行爲(wèi)類

}

publicvoidswim(){

System.out.println(“Allducksfloat,evendecoys!”);

}

}

2、FlyBehavior()接口與2個(gè)行爲(wèi)實(shí)現(xiàn)類

publicinterfaceFlyBehavior{

publicvoidfly();

}

publicclassFlyNoWayimplementsFlyBehavior{

publicvoidfly(){

System.out.println(“Icantfly”);

}

}

publicclassFlyWithWingsimplementsFlyBehavior{

publicvoidfly(){

System.out.println(“Imflying!”);

}

}

3、QuackBehavior()接口與2個(gè)行爲(wèi)實(shí)現(xiàn)類

PublicinterfaceQuackBehavior{

publicvoidquack();

}

publicclassQuackimplementsQuackBehavior{

publicvoidquack(){

System.out.println(“Quack”);

}

}

publicclassMuteQuackimplementsQuackBehavior{

publicvoidquack(){

System.out.println(“《Silence》”);

}

}

4、來看看如何設(shè)定FlyBehavior和QuackBehavior的實(shí)例變量(繼承)

publicclassMallardDuckextendsDuck{

publicMallardDuck(){

//綠頭鴨子使用Quack類處理呱呱叫,所以當(dāng)performQuack被調(diào)用時(shí),叫的責(zé)任被委託給Quack對象,

//而我們得到了真正的呱呱叫

quackBehavior=newQuack();

//使用FlyWithWings作爲(wèi)其FlyBehavior類型

flyBehavior=newFlyWithWings();

}

publicvoiddisplay(){

System.out.println(“ImarealMallardduck”);

}

}

5、製造一個(gè)新的鴨子類型

publicclassModelDuckextendsDuck{

publicModelDuck(){

flyBehavior=newFlyNoWay();//一開始我們的鴨子是不會飛的

quackBehavior=newQuack();

}

publicvoiddisplay(){

System.out.println(“Imamodelduck”);

}

}

6、建立一個(gè)新的FlyBehavior類型,火箭動力的飛行行爲(wèi)

publicclassFlyRocketPoweredimplementsFlyBehavior{

publicvoidfly(){

System.out.println(“Imflyingwitharocket”);

}

}

7、測試類

publicclassMiniDuckSimulator{

publicstaticvoidmain(String[]args){

Duckmallard=newMallardDuck();

//這會調(diào)用MallardDuck繼承來的performQuack方法,進(jìn)而委託給該對象的QuackBehavion對象處理

//也就是說調(diào)用繼承來的quackBehavion引用對象的quack()方法

mallard.performQuack();

mallard.performFly();

Duckmodel=newModelDuck();

//第一次調(diào)用performFly會被委託給flyBahavion對象,

//也就是FlyNoWay實(shí)例,該對象是在模型鴨子構(gòu)造器中設(shè)置的

model.performFly();

//這會調(diào)用繼承來的setter方法,把FlyRocketPowered火箭動力飛行行爲(wèi)設(shè)定到模型鴨子中,牛吧……

model.setFlyBehavior(newFlyRocketPowered());

//如果成功了,就意味著模型鴨子可以動態(tài)的改變它的飛行行爲(wèi)

model.performFly();

}

}

第117章第153章第45章第157章第116章第135章第180章第136章第116章第217章第64章第120章第44章第10章第124章第82章第123章第92章第73章第10章第125章第62章第218章第36章第47章第58章第98章第207章第228章第100章第153章第68章第130章第107章第62章第84章第153章第63章第116章第4章第175章第49章第207章第167章第17章第86章第41章第173章第78章第89章第195章第31章第189章第39章第59章第3章第78章第177章第39章第227章第198章第96章第141章第227章第219章第10章第53章第11章第130章第200章第98章第26章第93章第226章第136章第205章第183章第207章第184章第209章第175章第134章第221章第116章第191章第157章第209章第16章第222章第150章第84章第220章第157章第127章第212章第180章第187章第24章第205章
第117章第153章第45章第157章第116章第135章第180章第136章第116章第217章第64章第120章第44章第10章第124章第82章第123章第92章第73章第10章第125章第62章第218章第36章第47章第58章第98章第207章第228章第100章第153章第68章第130章第107章第62章第84章第153章第63章第116章第4章第175章第49章第207章第167章第17章第86章第41章第173章第78章第89章第195章第31章第189章第39章第59章第3章第78章第177章第39章第227章第198章第96章第141章第227章第219章第10章第53章第11章第130章第200章第98章第26章第93章第226章第136章第205章第183章第207章第184章第209章第175章第134章第221章第116章第191章第157章第209章第16章第222章第150章第84章第220章第157章第127章第212章第180章第187章第24章第205章
主站蜘蛛池模板: 慈利县| 开平市| 汕尾市| 九龙城区| 扶绥县| 永州市| 赞皇县| 丁青县| 二连浩特市| 大关县| 德安县| 绵竹市| 栾川县| 东至县| 宾阳县| 定州市| 东乡县| 无极县| 武川县| 象山县| 灵武市| 金沙县| 鄂伦春自治旗| 保亭| 吉木乃县| 合江县| 海淀区| 南丹县| 综艺| 华蓥市| 武威市| 中西区| 静安区| 赞皇县| 明水县| 云和县| 格尔木市| 新津县| 松江区| 大姚县| 马尔康县|