
需求:
1:模擬鴨子項(xiàng)目
從項(xiàng)目"模擬鴨子游戲"開始。
鴨子都會(huì)叫、會(huì)游泳。有的鴨子是紅頭的、有的鴨子是綠頭的。
分析:
從OO(Object?Oriented,面向?qū)ο?的角度設(shè)計(jì)這個(gè)項(xiàng)目。
鴨子的父類:
抽象的
1.都會(huì)gaga叫
2.抽象的外形(如:紅頭鴨、綠頭鴨等)
3.都會(huì)游泳
綜上所述,我們得到鴨子父類:
public?abstract?class?Duck?{
public??Duck(){};
//1:鴨子都會(huì)叫
public?void?quack(){
System.out.println("~嘎嘎叫~");
}
//2:抽象的外形
public?abstract?void??display();
//3:鴨子都會(huì)游泳
public?void?swim(){
System.out.println("~~swiming?~~");
}
}
具體實(shí)現(xiàn):
綠頭鴨:
public?class?GreenHeadDuck??extends??Duck{
@Override
public?void?display()?{
System.out.println("~~?i'm??GreenHeadDuck?~~?gaga");
}
}紅頭鴨:
public?class?RedHeadQuck?extends??Duck{
@Override
public?void?display()?{
System.out.println("~~?i'm??Read?~~?gaga");
}
}
新需求:
添加鴨子會(huì)飛的功能。
思考:
這個(gè)fly功能是放在父類中還是放到單個(gè)里面?
如果放到父類中,那么問(wèn)題來(lái)了。并不是所有的鴨子都會(huì)飛。如果放到父類中,就成了所有鴨子都會(huì)飛了。這個(gè)是不對(duì)的。
所以,我們從這里就可以看出如果使用繼承會(huì)導(dǎo)致的問(wèn)題;
對(duì)類的局部改變,尤其是父類的局部改變,會(huì)影響其他部分。這種影響會(huì)有溢出的效應(yīng)。
如果非要使用繼承方法,也是可以的。我們?cè)谧宇愔懈采w父類的方法。
如在綠頭鴨中將fly()方法覆蓋類。
public?void?Fly()?{
System.out.println("~~no?fly~~");
}
這個(gè)時(shí)候,又來(lái)新需求了了。需要一個(gè)石頭鴨子。我們知道石頭鴨子是不會(huì)飛、不會(huì)叫、不會(huì)游泳的
我們?nèi)绻^承了Duck類。那么,就要不停的去填坑的。
所以,我們可以看出這種需求下如果還是用OO面向?qū)ο笤瓌t來(lái)的話,會(huì)出現(xiàn):
父類挖的一個(gè)坑,每個(gè)子類都要來(lái)填坑。增加了工作量。其復(fù)雜度是O(N^2).這這種需求下,如果是這樣設(shè)計(jì)的話就不是一個(gè)好的設(shè)計(jì)方式。
我們就要思考,需要新的設(shè)計(jì)模式,來(lái)應(yīng)對(duì)項(xiàng)目的擴(kuò)展性,降低項(xiàng)目的復(fù)雜度。
1)分析項(xiàng)目變化于不變化的部分,提取變化部分、抽象成接口+實(shí)現(xiàn);
根據(jù)上面原則,我們?cè)趤?lái)看看鴨子游戲項(xiàng)目:
鴨子哪些功能會(huì)根據(jù)新需求變化呢?
如鴨子叫、飛行等等。
這個(gè)時(shí)候,我們可以設(shè)計(jì)如下接口:
鴨子飛行為的接口:
interface?FlyBehaviro{
void?fly();
}
鴨子叫行為的接口:
interface?Quackehavior{
void?quack();
}
有了這兩個(gè)接口之后,鴨子想飛實(shí)現(xiàn)飛行為的接口、鴨子想叫實(shí)現(xiàn)叫的接口。這樣組合起來(lái)更方便。
這樣做的好處:
新增行為簡(jiǎn)單了,行為類更好的被復(fù)用了,組合更方便了,既有繼承帶來(lái)的復(fù)用好處,而其還沒(méi)有挖坑。
根據(jù)上面分析,我們重新設(shè)計(jì)鴨子模式:
1:將行為提取成抽象接口
FlyBeahavior
QuackBehavior
2:在父類Duck中,將各個(gè)抽象接口作為屬性
@Data
public?abstract?class?Duck?{
public??Duck(){}
/**
*?飛行行為
*/
FlyBehavior?myFlyBehavior;
QuackBehavior?myQuackBehavior;
public?void?fly(){
myFlyBehavior.fly();
}
public?void?quack(){
myQuackBehavior.QuackBehavior();
}
public?abstract?void?display();
}
3:在創(chuàng)建具體鴨子對(duì)象的時(shí)候,將行為實(shí)例化到構(gòu)造器中。如下:
public?class?GreenHeadDuck??extends?Duck?{
public?GreenHeadDuck(){
myFlyBehavior?=?new?GoodFlyBehavior();
myQuackBehavior?=?new?GaGaQuackBehavior();
}
@Override
public?void?display()?{
System.out.println("~~?i'm??GreenHeadDuck?~~?gaga");
}
}
在測(cè)試方法中,父類實(shí)例化使用子類對(duì)象。如下:
Duck?greenHeadDuck?=?new?GreenHeadDuck();
greenHeadDuck.display();
greenHeadDuck.fly();
greenHeadDuck.quack();
