java鴨子全代碼 鴨子類型 編程

java編程題:雞鴨豬狗4種動物,共30 條腿,要求輸出所有可能的動物組合

public class Test {

創(chuàng)新互聯(lián)主營興縣網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都app軟件開發(fā),興縣h5微信平臺小程序開發(fā)搭建,興縣網(wǎng)站營銷推廣歡迎興縣等地區(qū)企業(yè)咨詢

public static void main(String[] args) {

int count = 30;

int possibleNum = 1;

for (int i = 4; i = count; i += 4) {

for (int j = 4; j = count - i; j += 4) {

for (int x = 2; x = count - (j + i); x += 2) {

if (x + j + i == count ) {

System.out.println("*************Possible " + possibleNum++ + ": ");

System.out.println("pig = " + (i/4));

System.out.println("dog = " + (j/4));

System.out.println("chicken = " + (x/2));

}

for (int y = 2; y = count - (x + j + i); y += 2) {

if (y + x + j + i == count ) {

System.out.println("*************Possible " + possibleNum++ + ": ");

System.out.println("pig = " + (i/4));

System.out.println("dog = " + (j/4));

System.out.println("chicken = " + (x/2));

System.out.println("duck = " + (y/2));

}

}

}

}

}

}

}

一道java題

我建議你還是先好好學(xué)習(xí)java的基礎(chǔ),讓后再看代碼,protected FlyBehavior (3); 是創(chuàng)建一個名字為(3)的對象。我想告訴你這個以后,別的都不用說了吧。因為4更3一樣。5和6就是對象調(diào)用自己的方法了。

軟件設(shè)計模式鴨子模擬器

假設(shè)我們需要設(shè)計出各種各樣的鴨子,一邊游泳戲水, 一邊呱呱叫。很明顯這時我們需要設(shè)計了一個鴨子超類(Superclass),并讓各種鴨子繼承此超類。

public abstract class Duck {

public void Swim() {

//會游泳

}

public abstract display();//各種外觀不一樣,所以為抽象

public void Quack() {

//會叫

}

}

每一只鴨子就繼承Duck類

public class MallardDuck extends Duck {

public void display() {

// 外觀是綠色的

}

}

public class RedheadDuck extends Duck{

public void display(){

// 外觀是紅色的

}

}

好了,我們完成這些后,但是發(fā)現(xiàn)我們需要有一些鴨子是會飛的,應(yīng)該怎么修改呢?

也許你要說這很簡單,在Duck類里面直接加入一個fly()方法,不就可以了。

public abstract class Duck {

public void Swim() {

//會游泳

}

public abstract display();//各種外觀不一樣,所以為抽象

public void Quack() {

//會叫

}

public void fly(){

//會飛

}

}

這時你會發(fā)現(xiàn)所有的鴨子都變成了會飛的,很明顯這是不對了,例如橡皮鴨顯然就不是了。

你也許想到了另一種方法,在會飛的鴨子類里才添加該方法不就可以了嘛,

public class MallardDuck extend Duck{

public void display(){

// 外觀是綠色的

}

public void fly(){

//會飛

}

}

這個方法看起來是很不錯,可是有很多種鴨子都會飛的時候,代碼的復(fù)用性很明顯是不夠好的,你不得不在

每一個會飛的鴨子類里去寫上同一個fly()方法,這可不是個好主意.

可能你又想到另一個方法:采用繼承和覆蓋,在Duck類里實現(xiàn)fly()方法,在子類里如果不會飛的就覆蓋它

public abstract class Duck {

public void Swim() {

//會游泳

}

public abstract display();//各種外觀不一樣,所以為抽象

public void Quack(){

//會叫

}

public void fly(){

//會飛

}

}

//橡皮鴨吱吱叫,不會飛

public class RubberDuck extend Duck{

public void quack(){

//覆蓋成吱吱叫

}

public void display{

//外觀是橡皮鴨

}

public void fly{

//什么也不做

}

}

這樣我們真實現(xiàn)了確實能飛的鴨子才可以飛起來了,看起來主意不錯!問題到這兒似乎得到了解決

但我們現(xiàn)在有了一種新的鴨子,誘鉺鴨(不會飛也不會叫),看來需要這樣來寫

public class DecoyDuck extend Duck{

public void quack(){

//覆蓋,變成什么也不做

}

public void display(){

//誘餌鴨

}

public void fly(){

//覆蓋,變成什么也不做

}

}

每當(dāng)有新的鴨子子類出現(xiàn)或者鴨子新的特性出現(xiàn),就不得不被迫在Duck類里添加并在所有子類里檢查可能需要覆蓋fly()和quark()...這簡直是無窮盡的惡夢。所以,我們需要一個更清晰的方法,讓某些(而不是全部)鴨子類型可飛或可叫。讓鴨子的特性能有更好的擴展性。

用一下接口的方式把fly()取出來,放進一個Flyable接口中,這樣只有會飛的鴨子才實現(xiàn)這個接口,當(dāng)然我們也可以照此來設(shè)計一個Quackbable接口,因為不是所有的鴨子都會叫,也只讓會叫的鴨子才去實現(xiàn)這個接口.

但這個方法和上面提到的在子類里去實現(xiàn)fly一樣笨,如果幾十種都可以飛,你得在幾十個鴨子里去寫上一樣的fly(),如果一旦這個fly有所變更,你將不得不找到這幾十個鴨子去一個一個改它們的fly()方法。

因為改變鴨子的行為會影響所有種類的鴨子,而這并不恰當(dāng)。Flyable與Quackable接口一開始似乎還挺不錯, 解決了問題( 只有會飛的鴨子才繼承Flyable) , 但是Java的接口不具有實現(xiàn)代碼, 所以繼承接口無法達到代碼的復(fù)用。這意味著:無論何時你需要修改某個行為,你必須得往下追蹤并修改每一個定義此行為的類。

策略模式的第一原則:找出應(yīng)用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。 好吧,回頭看一下這個Duck類,就我們目前所知,除了fly()和quack()的問題之外,Duck類還算一切正常,主要是鴨子的行為總是可能變化的,讓我們頭痛就在于這些行為的變化,那我們就把這些行為獨立出來。

為了要把這兩個行為從Duck 類中分開, 我們將把它們自Duck 類中取出,建立一組新類代表每個行為。我們建立兩組類(完全遠離Duck類),一個是「fly」相關(guān)的,一個是「quack」相關(guān)的,每一組類將實現(xiàn)各自 的動作。比方說,我們可能有一個類實現(xiàn)「呱呱叫」,另一個類實現(xiàn)「吱吱叫」,另一個類實現(xiàn)「安靜」。我們利用接口代表每組行為,比方說, FlyBehavior來代表飛的行為,QuackBehavior代表叫的行為,而讓每一種行為具體類來實現(xiàn)該行為接口。

在此,我們有兩個接口,F(xiàn)lyBehavior和QuackBehavior,還有它們對應(yīng)的類,負(fù)責(zé)實現(xiàn)具體的行為:

public interface FlyBehavior {

public void fly();

}

public class FlyWithWings implements FlyBehavior{

public void fly{}{

//實現(xiàn)鴨子飛行

}

}

public class FlyNoWay implements FlyBehavior{

public void fly{}{

//什么也不做,不會飛

}

}

public interface QuackBehavior{

public void quack();

}

public class Quack implements QuackBehavior{

public void quack(){

//實現(xiàn)鴨子呱呱叫

}

}

public class Squeak implements QuackBehavior{

public void quack(){

//實現(xiàn)鴨子吱吱叫

}

}

public class MuteQuack implements QuackBehavior{

public void quack(){

//什么也不做,不會叫

}

}

實際上這樣的設(shè)計,我們已經(jīng)可以讓飛行和呱呱叫的動作被其他的對象復(fù)用,因為這些行為已經(jīng)與鴨子類無關(guān)了。如果我們新增一些行為,也不會影響到既有的行為類,也不會影響有已經(jīng)使用到飛行行為的鴨子類。

好了,我們設(shè)計好鴨子的易于變化的行為部分后,該到了整合鴨子行為的時候了。

這時我們該想到策略模式的另一個原則了:

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

首先, 在鴨子中加入兩個實例變量,分別為「flyBehavior」與「quackBehavior」,聲明為接口類型( 而不是具體類實現(xiàn)類型), 每個變量會利用多態(tài)的方式在運行時引用正確的行為類型( 例如:FlyWithWings 、Squeak...等)。我們也必須將Duck類與其所有子類中的fly()與quack()移除,因為這些行為已經(jīng)被搬移到FlyBehavior與 Quackehavior類中了,用performFly()和performQuack()取代Duck類中的fly()與quack()。

public abstract class Duck(){

FlyBehavior flyBehavior;

QuackBehavior quackBehavior;

public void swim(){

//會游泳

}

public abstract void display();//各種外觀不一樣,所以為抽象

public void performQuack(){

quackBehavior.quack();

}

public void performFly(){

flyBehavior.fly();

}

}

很容易,是吧?想進行呱呱叫的動作,Duck對象只要叫quackBehavior對象

去呱呱叫就可以了。在這部分的代碼中,我們不在乎QuackBehavior 接口的對象到底是什么,我們只關(guān)心該對象

知道如何進行呱呱叫就夠了。

好吧! 現(xiàn)在來關(guān)心如何設(shè)定flyBehavior 與quackBehavior的實例變量。

看看MallardDuck類:

public class MallardDuck extends Duck {

public MallardDuck() {

\\綠頭鴨使用Quack類處理呱呱叫,所以當(dāng)performQuack() 被調(diào)用,就把責(zé)任委托給Quack對象進行真正的呱呱叫。

quackBehavior = new Quack();

\\使用FlyWithWings作為其FlyBehavior類型。

flyBehavior = new FlyWithWings();

}

}

所以,綠頭鴨會真的『呱呱叫』,而不是『吱吱叫』,或『叫不出聲』。這是怎么辦到的?當(dāng)MallardDuck實例化時,它的構(gòu)造器會

把繼承來的quackBehavior實例變量初始化成Quack類型的新實例(Quack是QuackBehavior的具體實現(xiàn)類)。同樣的處理方式也可以用在飛行行為上: MallardDuck 的構(gòu)造器將flyBehavior 實例變量初始化成FlyWithWings 類型的實例(

FlyWithWings是FlyBehavior的具體實現(xiàn)類)。

輸入下面的Duck類(Duck.java) 以及MallardDuck 類MallardDuck.java),并編譯之。

public abstract class Duck {

//為行為接口類型聲明兩個引用變量, 所有鴨子子類(在同一個packge)都繼承它們。

FlyBehavior flyBehavior;

QuackBehavior quackBehavior;

public Duck() {

}

public abstract void display();

public void performFly() {

flyBehavior.fly();//委托給行為類

}

public void performQuack() {

quackBehavior.quack();//委托給行為類

}

public void swim() {

System.out.println("All ducksfloat, even decoys!");

}

}

public class MallardDuck extends Duck {

public MallardDuck() {

quackBehavior = newQuack();

flyBehavior = newFlyWithWings();

}

public void display() {

System.out.println("I’m a real Mallard duck");

}

}

輸入FlyBehavior接口(FlyBehavior.java)與兩個行為實現(xiàn)類(FlyWithWings.java與FlyNoWay.java),并編譯之。

public interface FlyBehavior {//所有飛行行為類必須實現(xiàn)的接口

public void fly();

}

public class FlyWithWings implements FlyBehavior {//這是飛行行為的實現(xiàn), 給「真會」飛的鴨子用 .. .

public void fly() {

System.out.println("I’m flying!!");

}

}

public class FlyNoWay implements FlyBehavior {//這是飛行行為的實現(xiàn), 給「不會」飛的鴨子用( 包括橡皮鴨和誘餌鴨)

public void fly() {

System.out.println("I can’t fly");

}

}

輸入QuackBehavior接口(QuackBehavior.java)及其三個實現(xiàn)類(Quack.java、MuteQuack.java、Squeak.java),并編譯之。

public interface QuackBehavior {

public void quack();

}

public class Quack implements QuackBehavior {

public void quack() {

System.out.println(“Quack”);

}

}

public class MuteQuack implements QuackBehavior {

public void quack() {

System.out.println(“ Silence ”);

}

}

public class Squeak implements QuackBehavior {

public void quack() {

System.out.println(“Squeak”);

}

}

輸入并編譯測試類(MiniDuckSimulator.java)

public class MiniDuckSimulator {

public static void main(String[] args) {

Duck mallard = new MallardDuck();

mallard.display();

//這會調(diào)用MallardDuck繼承來的performQuack() ,進而委托給該對象的QuackBehavior對象處理。(也就是說,調(diào)用繼承來的quackBehavior的quack())

mallard.performQuack();

//至于performFly() ,也是一樣的道理。

mallard.performFly();

}

}

運行結(jié)果:

I’m a real Mallard duck

Quack

I’m flying!!

雖然我們把行為設(shè)定成具體的類(通過實例化類似Quack 或FlyWithWings的行為類, 并指定到行為引

用變量中),但是還是可以在運行時輕易地改變該行為。

所以,目前的作法還是很有彈性的,只是初始化實例變量的作法不夠彈性罷了。

我們希望一切能有彈性,畢竟,正是因為一開始的設(shè)計的鴨子行為沒有彈性,才讓我們走到現(xiàn)在這條路。

我們還想能夠「指定」行為到鴨子的實例, 比方說, 想要產(chǎn)生綠頭鴨實例,并指定特定「類型」的飛行

行為給它。干脆順便讓鴨子的行為可以動態(tài)地改變好了。換句話說,我們應(yīng)該在鴨子類中包含設(shè)定行為的方法。

因為quackBehavior實例變量是一個接口類型,所以我們是能夠在運行時,透過多態(tài)動態(tài)地指定不同的QuickBehavior實現(xiàn)類給它。

我們在鴨子子類透過設(shè)定方法(settermethod)設(shè)定鴨子的行為,而不是在鴨子的構(gòu)造器內(nèi)實例化。

在Duck類中,加入兩個新方法:從此以后,我們可以「隨時」調(diào)用這兩個方法改變鴨子的行為。

public strate class Duck(){

FlyBehavior flyBehavior;

QuackBehavior quackBehavior;

public void setFlyBehavior(FlyBehavior fb) {

flyBehavior = fb;

}

public void setQuackBehavior(QuackBehavior qb) {

quackBehavior = qb;

}

}

好了,讓我們再制造一個新的鴨子類型:模型鴨(ModelDuck.java)

public class ModelDuck extends Duck {

public ModelDuck() {

flyBehavior = new FlyNoWay();//初始狀態(tài),我們的模型鴨是不會飛的。

quackBehavior = new Quack();//初始狀態(tài),我們的模型鴨是可以叫的.

}

public void display() {

System.out.println("I’m a modelduck");

}

}

建立一個新的FlyBehavior類型(FlyRocketPowered.java)

public class FlyRocketPowered implements FlyBehavior {

// 我們建立一個利用火箭動力的飛行行為。

public void fly() {

System.out.println("I’m flying with arocket!");

}

}

改變測試類(MiniDuckSimulator.java),加上模型鴨,并使模型鴨具有火箭動力。

public class MiniDuckSimulator {

public static void main(String[] args) {

Duck mallard = new MallardDuck();

mallard.performQuack();

mallard.performFly();

Duck model = new ModelDuck();

//第一次調(diào)用performFly() 會被委托給flyBehavior對象(也就是FlyNoWay對象),該對象是在模型鴨構(gòu)造器中設(shè)置的。

model.performFly();

//這會調(diào)用繼承來的setter 方法,把火箭動力飛行的行為設(shè)定到模型鴨中。哇咧! 模型鴨突然具有火箭動力飛行能力。

model.setFlyBehavior(new FlyRocketPowered());

//如果成功了, 就意味著模型鴨動態(tài)地改變行為。如果把行為的實現(xiàn)綁死在鴨子類中, 可就無法做到這樣。

model.performFly();

}

}

運行一下,看下結(jié)果

I’m a real Mallard duck

Quack

I’m flying!!

I’m a model duck

I can’t fly

I’m flying with a rocket!

如同本例一般,當(dāng)你將兩個類結(jié)合起來使用,這就是組合(composition)。這種作法和『繼承』不同的地方在于,

鴨子的行為不是繼承而來,而是和適當(dāng)?shù)男袨閷ο蟆航M合』而來。

這是一個很重要的技巧。其實是使用了策略模式中的第三個設(shè)計原則, 多用組合,少用繼承。

現(xiàn)在來總結(jié)一下,鴨子的行為被放在分開的類中,此類專門提供某行為的實現(xiàn)。

這樣,鴨子類就不再需要知道行為的實現(xiàn)細(xì)節(jié)。

鴨子類不會負(fù)責(zé)實現(xiàn)Flyable與Quackable接口,反而是由其他類專門實現(xiàn)FlyBehavior與QuackBehavior,

這就稱為「行為」類。由行為類實現(xiàn)行為接口,而不是由Duck類實現(xiàn)行為接口。

這樣的作法迥異于以往,行為不再是由繼承Duck超類的具體實現(xiàn)而來, 或是繼承某個接口并由子類自行實現(xiàn)而來。

(這兩種作法都是依賴于「實現(xiàn)」, 我們被實現(xiàn)綁得死死的, 沒辦法更改行為,除非寫更多代碼)。

在我們的新設(shè)計中, 鴨子的子類使用接口( FlyBehavior與QuackBehavior)所表示的行為,所以實際的實現(xiàn)不會被

綁死在鴨子的子類中。( 換句話說, 特定的實現(xiàn)代碼位于實現(xiàn)FlyBehavior與QuakcBehavior的特定類中),這樣我們就獲得了更大的靈活性和可擴展性。

網(wǎng)頁標(biāo)題:java鴨子全代碼 鴨子類型 編程
文章轉(zhuǎn)載:http://muchs.cn/article22/hgchcc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)站策劃、網(wǎng)站導(dǎo)航建站公司、小程序開發(fā)定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

手機網(wǎng)站建設(shè)