設計模式學習(一)之策略模式

把模式裝進腦子裏,然後在你的設計和已有的應用中,尋找何處可以使用它們。
每個設計模式背後的精神所在:
設計原則:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起
如果每次新需求一來,都會使某些方面的代碼發生變化,那麼就可以確定,這部分的代碼需要被抽出來,和其他穩定的代碼有所區分。
把會變化的部分取出並封裝起來,以便以後可以輕易的改動或擴充此部分,而不影響不需要變化的其它部分

鴨子模擬
所有的鴨子都會呱呱叫Quack,也會游泳Swim,所以由超類負責處理這部分的實現代碼
每一種鴨子的外觀都不同,所以display方法是抽象的

新需求:我們讓有的鴨子可以飛起來
先在Duck類上加上fly方法,然後所有的鴨子都繼承fly方法

問題來了:有的鴨子不會飛,但是也具有了飛這個行爲,比如橡皮鴨子
在超類中加上了新的行爲,使得某些不適合該行爲的子類也具有了該行爲,對代碼的局部修改,影響層面可不是局部
繼續按照這個繼承這個思路去解決問題,可以覆蓋fly方法,讓fly方法什麼都不做

問題又來了:如果以後加入木頭鴨子,不會飛也不會叫。
很難知道鴨子的全部行爲,每次新增子類,都要被迫檢查各個行爲
用接口來解決,但是首先是針對實現編程
我們可以把fly從超類中取出來,放到一個Flyable接口中,只有會飛的鴨子才實現此接口,同樣的方式,也可以用來設計一個Quackable接口,只有會叫的鴨子才下實現這個接口

問題來了:上面的接口設計造成了代碼不能複用,每個子類都得在用到的時候實現接口
因爲java接口不具有實現代碼,所以繼承接口無法達到代碼複用

設計原則:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起
系統中的某些改變不影響其它部分
我們現在知道Duck類內的fly和quack會隨着鴨子的不同而改變,爲了要把這兩個行爲從Duck類中分開,我們將把它們從Duck類中取出來,建立一組新類來代表每個行爲。
設計原則:正對接口編程,而不是針對實現編程。
之前的行爲來自於Duck超類的具體實現,或是繼承某個接口並由子類自行實現而來。這兩種做法都一來於實現。
先來看個簡單的多態例子

我們不知道子類型是什麼,我們只關心它知道如何正確的進行makeSound的動作就可以了
整體的格局
一組行爲,一族算法

關係可以是
(是一個)
(有一個)
(實現)
設計原則:多用組合,少用繼承

策略模式:定義了算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶
下面,我們用代碼來實現終極版類圖
package com.alvin.strategy;

import com.alvin.strategy.behavior.FlyBehavior;
import com.alvin.strategy.behavior.QuackBehavior;

public abstract class Duck {
	protected FlyBehavior flyBehavior;
	protected QuackBehavior quackBehavior;
	
	public void swim(){
		System.out.println("swim");
	}
	
	abstract public void display();
	
	public void setFlyBehavior(FlyBehavior flyBehavior){
		this.flyBehavior = flyBehavior;
	}
	
	public void setQuackBehavior(QuackBehavior quackBehavior){
		this.quackBehavior = quackBehavior;
	}
	
	public void performFly() {
		flyBehavior.fly();
	}
	
	public void performQuack() {
		quackBehavior.quack();
	}

}
package com.alvin.strategy.subduck;

import com.alvin.strategy.Duck;
import com.alvin.strategy.behavior.impl.FlyWithWings;
import com.alvin.strategy.behavior.impl.Quack;

public class MallardDuck extends Duck{
	
	public MallardDuck(){
		flyBehavior = new FlyWithWings();
		quackBehavior = new Quack();
	}

	@Override
	public void display() {
		System.out.println("MallardDuck");
	}

}
package com.alvin.strategy.subduck;

import com.alvin.strategy.Duck;
import com.alvin.strategy.behavior.impl.FlyWithWings;
import com.alvin.strategy.behavior.impl.Squeak;

public class RedheadDuck extends Duck {
	
	public RedheadDuck(){
		flyBehavior = new FlyWithWings();
		quackBehavior = new Squeak();
	}

	@Override
	public void display() {
		System.out.println("RedheadDuck");

	}

}
package com.alvin.strategy.behavior;

public interface FlyBehavior {

	void fly();
}
package com.alvin.strategy.behavior;

public interface QuackBehavior {
	void quack();

}
package com.alvin.strategy.behavior.impl;

import com.alvin.strategy.behavior.FlyBehavior;

public class FlyNoWay implements FlyBehavior{

	@Override
	public void fly() {
		System.out.println("FlyNoWay");
		
	}

}
package com.alvin.strategy.behavior.impl;

import com.alvin.strategy.behavior.FlyBehavior;

public class FlyWithWings implements FlyBehavior{

	@Override
	public void fly() {
		System.out.println("FlyWithWings");
	}

}
package com.alvin.strategy.behavior.impl;

import com.alvin.strategy.behavior.QuackBehavior;

public class MuteQuack implements QuackBehavior {

	@Override
	public void quack() {
		System.out.println("MuteQuack");

	}

}
package com.alvin.strategy.behavior.impl;

import com.alvin.strategy.behavior.QuackBehavior;

public class Quack implements QuackBehavior{

	@Override
	public void quack() {
		System.out.println("Quack");
		
	}

}
package com.alvin.strategy.behavior.impl;

import com.alvin.strategy.behavior.QuackBehavior;

public class Squeak implements QuackBehavior{

	@Override
	public void quack() {
		System.out.println("Squeak");
		
	}

}
package com.alvin.strategy;

import com.alvin.strategy.behavior.impl.Squeak;
import com.alvin.strategy.subduck.MallardDuck;

public class Run {
	public static void main(String[] args) {
		Duck duck = new MallardDuck();
		duck.performFly();
		duck.performQuack();
		duck.setQuackBehavior(new Squeak());
		duck.performQuack();
	}

}
運行結果

FlyWithWings
Quack
Squeak




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章