国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

策略模式學習2

2019-11-08 02:09:37
字體:
來源:轉載
供稿:網友

接著我的上一篇文章策略模式學習1。

讓我們來回顧一下上面設計中橡皮鴨類的代碼,并提出一下問題。

/** * 橡皮鴨 * @author Administrator * */public class RubberDuck extends Duck {		@Override	void display() {		System.out.PRintln("橡皮鴨...");	}		/*	 * 橡皮鴨子不會呱呱叫	 * 但是問題來了,這個橡皮鴨子會飛?	 * 那設計人員會說:一樣覆蓋掉就好	 */	@Override	public void quack() {		//覆蓋超類的呱呱叫		System.out.println("吱吱叫...");	}		@Override	void fly() {		//覆蓋,變成什么事兒都不做		;	}		/*	 * 那么問題來了,以后每個月更新,常常會出現新的鴨子子類,這要被迫每次檢查	 * 并可能覆蓋quack() 和 fly() 這簡直就是無窮無盡的噩夢!!!!	 * 這樣設計的缺點:	 * 1.代碼在多個子類中重復	 * 2.運行時的行為不容易被改變	 * 3.改變會牽一發動全身,造成其他鴨子不想要的改變	 * 4.很難知道鴨子的全部行為,因為有了不屬于它本身的行為。	 */		//重復代碼變多,那么你認為覆蓋幾個方法就算是差勁,那么對于48個Duck子類都要稍微修改一下	//飛行的行為,你又怎么說?需求:會飛的鴨子中,飛的動作可能有多種變化.	}

因此我們可以看到,利用繼承來提供Duck的行為,會導致以上所述的問題以及缺點。那利用接口如何?將飛行方法和呱呱叫的方法做成一個接口,分別讓具備這兩個行為的鴨子實現這個接口,就能夠解決不再會有會飛的鴨子。但是缺點是:造成了代碼無法復用(雖然鴨子類中實現了飛行的方法,但是這個鴨子在某個場景下又想要其他類型的飛行方法呢?這有點類似于游戲中的升級,解鎖了某技能或在某個副本中,會以新的行為出現)。這又跳進了另外一個坑。

另外,如果飛行的動作可能還有多種變化呢?比如火箭式飛行,螺旋式飛行等等。

軟件開發的一個不變的真理:改變(change).不管軟件設計得多好,一段時間之后,總是需要成長和改變,否則軟件就會“死亡”。

利用Flyable和Quackable一開始似乎還不錯,解決了只有會飛的鴨子才實現Flyable,但是java接口不具有實現代碼,所以實現接口無法達到代碼的復用。這就意味著無論何時你需要修改某個行為,你必須得往下追蹤到并在每一個定義此行為的類中修改它,一不小心,可能會造成新的錯誤。

幸運的是,這里有一個設計原則:

找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。換句話說:如果每次新的需求一來,都會使某方面的代碼發生變化,那么你就可以確定,這部分的代碼需要被抽出來,和其他穩定的代碼有所區分。對這個原則的另外一種思考方式:把會變化的部分取出并封裝出來,以便以后可以輕易地改動或擴充此部分,而不影響不需要變化的其他部分。

我們知道Duck類的fly()和quack()會隨著鴨子的不同而改變。因此我們把這兩個行為從Duck類中分離出來,建立一組新類來代表每個行為。

如何設計鴨子的行為?我們想要產生一個新的綠頭鴨實例,并指定特定的“類型”的飛行行為給它。那么干脆順便讓鴨子的行為可以動態的改變好了。換句話說:我們應該在鴨子類中包含設定行為的方法,這樣就可以在“運行時”動態地“改變”綠頭鴨的飛行行為。

設計原則:針對接口編程,而不是針對實現編程。

public abstract class Duck {	FlyBehavior flyBehavior;	QuackBehavior quackBehavior;	// 行為變量被聲明為行為 "接口" 類型	public void swim() {		System.out.println("游來游去...");	}		abstract void display();	//鴨子對象不親自處理呱呱叫行為,而是委托給quackBehavior引用的對象去執行	void performQuack() {		quackBehavior.quack();	}	void performFly() {		flyBehavior.fly();	}	public FlyBehavior getFlyBehavior() {		return flyBehavior;	}	public void setFlyBehavior(FlyBehavior flyBehavior) {		this.flyBehavior = flyBehavior;	}	public QuackBehavior getQuackBehavior() {		return quackBehavior;	}	public void setQuackBehavior(QuackBehavior quackBehavior) {		this.quackBehavior = quackBehavior;	}		/*public void quack() {		System.out.println("呱呱叫...");	}		void fly(){		System.out.println("飛來飛去...");	}*/		//鴨子的其他方法}
public interface FlyBehavior {	void fly();}
public class FlyWithWings implements FlyBehavior {	@Override	public void fly() {		System.out.println("這里實現了所有有翅膀的鴨子飛行動作...");	}}
public class FlyNoWay implements FlyBehavior {	@Override	public void fly() {		//什么都不做,不會飛		System.out.println("I can't fly!");	}}
public class FlyByRocky implements FlyBehavior {	@Override	public void fly() {		// 新增了一個火箭式的飛行		System.out.println("火箭式的飛行...");	}}
public interface QuackBehavior {	void quack();}
public class Quack implements QuackBehavior {	@Override	public void quack() {		// 實現鴨子呱呱叫		System.out.println("呱呱叫...");	}}
public class Squeak implements QuackBehavior {	@Override	public void quack() {		// 橡皮鴨子吱吱叫		System.out.println("吱吱叫...");	}}
public class MallardDuck extends Duck {	@Override	void display() {		System.out.println("綠頭鴨..");	}}
public class ModelDuck extends Duck {		public ModelDuck(){		this.flyBehavior = new FlyNoWay();		this.quackBehavior = new MuteQuack();	}	@Override	void display() {		// 這是一只模型鴨		System.out.println("模型鴨...");	}		}
// 新增一個鴨鳴器,用來捕獲其他真正鴨子public class DuckCall implements QuackBehavior{	QuackBehavior quack;		public QuackBehavior getQuack() {		return quack;	}	public void setQuack(QuackBehavior quack) {		this.quack = quack;	}	@Override	public void quack() {		quack.quack();	}	}
//測試類public class MiniDuckSimulator {	public static void main(String[] args) {		/*Duck mallard = new MallardDuck();		mallard.setFlyBehavior(new FlyWithWings());		mallard.setQuackBehavior(new Quack());		mallard.performFly();		mallard.performQuack();*/				/*Duck modelDuck = new ModelDuck();		modelDuck.performFly();		modelDuck.setFlyBehavior(new FlyByRocky());//模型鴨可以動態地改變飛行行為		modelDuck.setQuackBehavior(new MuteQuack());		modelDuck.performFly();*/				//實現一個鴨鳴器用來誘捕野鴨		DuckCall duckCall = new DuckCall();		duckCall.setQuack(new Quack());		duckCall.quack();//利用多態,可以動態的模擬各種叫聲	}}
public class MuteQuack implements QuackBehavior {	@Override	public void quack() {		// 什么都不做,不會叫		;	}	/*	 * 這樣設計,可以讓飛行和呱呱叫的動作被其他的對象復用,因為這樣行為已經與鴨子無關了	 * 而我們可以新增一些行為,不會影響到既有的行為類,不會影響“使用”到飛行行為的鴨子類了。	 * 有了繼承的“復用”的好處,卻沒有了繼承所帶來的包袱	 */}這里也用到另外一個設計原則:多用組合,少用繼承。

“有一個”可能比“是一個”更好。有一個關系相當有趣,每個鴨子都有一個FlyBehavior和QuackBehavior,當你將兩個類結合起來使用,如通本例一般,這就是用到了組合。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 衢州市| 卢氏县| 资阳市| 博湖县| 桐乡市| 甘肃省| 云阳县| 万山特区| 广水市| 玛沁县| 长岛县| 从江县| 临桂县| 汝阳县| 乌兰察布市| 沅陵县| 沈阳市| 岚皋县| 金沙县| 德昌县| 建平县| 洞口县| 柯坪县| 化州市| 乃东县| 多伦县| 龙井市| 洪雅县| 大石桥市| 盐山县| 景泰县| 张家口市| 桃园县| 囊谦县| 北碚区| 黄骅市| 东海县| 邓州市| 安阳市| 白城市| 昭苏县|