設計模式之策略模式

說明:以下內容是學習Head First後自行整理的筆記。內容和程序均來自於該書


策略模式:定義了算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓算法的變化獨立於使用算法的客戶。


概念理解起來生硬,下面用一個鴨子的例子說明。

有一個模擬鴨子的遊戲。遊戲中有各種各樣的鴨子,它們可以游泳,呱呱叫。按照之前的設計一般是這樣的:有一個鴨子的超類Duck,有swim、quack的方法,然後不同的鴨子類去繼承它。

這個時候多了一個需求,要讓鴨子會飛,很自然你會在Duck裏面去加一個fly方法。

仔細想一想這種設計思路,是不是會存在問題。

1、如果你在Duck裏對fly等方法做了實現,這個時候會出現問題,那就是並不是所有的鴨子都是會飛的,比如只有野鴨子會飛,橡皮鴨並不會飛。

2、當然你會說我會把實現放到子類中,超類並不做實現。那麼另一個問題自然會出現,那就是如果野鴨子跟水鴨子都是會飛的,而且都是一樣的飛法,那fly這個方法不就會被寫了兩次甚至跟多,這樣是不利於維護的。而且如果遊戲中有另一個類:鵝,它也是會飛的,那就更加麻煩了。


所以這個時候策略模式就發揮作用了

下圖是設計的思路

wKioL1VYNDGR15DKAABFLrezVbA364.gif


下面是代碼

Duck.java

package bean;


public abstract class Duck {

	public Duck(){};
	
	FlyBehavior flyBehavior;
	QuackBehavior quackBehavior;
	
	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 swim(){
		System.out.println();
	}
	
	public void fly(){
		flyBehavior.fly();
	}
	
	public void quack(){
		quackBehavior.quack();
	}
}

FlyBehavior.java

package bean;

public interface FlyBehavior {

	public void fly();
	
}

FlyWithWings.java

package bean;

public class FlyWithWings implements FlyBehavior {

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("I fly with wing!");
	}

}

FlyNoWay.java

package bean;

public class FlyNoWay implements FlyBehavior {

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("I can't fly");
	}

}

QuackBehavior.java

package bean;

public interface QuackBehavior {

	public void quack();
	
}

QuackGaGa.java

package bean;

public class QuackGaGa implements QuackBehavior {

	@Override
	public void quack() {
		// TODO Auto-generated method stub
		System.out.println("ga ga");
	}

}

QuackNoWay.java

package bean;

public class QuackNoWay implements QuackBehavior {

	@Override
	public void quack() {
		// TODO Auto-generated method stub
		System.out.println("I can't quack");
	}

}

CleverDuck,java

package bean;

public class CleverDuck extends Duck {

	public CleverDuck(){
		this.flyBehavior = new FlyWithWings();
		this.quackBehavior = new QuackGaGa();
	}
	
}

StupidDuck.java

package bean;

public class StupidDuck extends Duck {

	public StupidDuck(){
		this.flyBehavior = new FlyNoWay();
		this.quackBehavior = new QuackNoWay();
	}
	
}



設計原則:

1、針對接口編程,而不是針對實現編程(這個很好理解)

2、多用組合,少用繼承。(如本例中,鴨子的行爲不是靠繼承得來的,而是通過行爲對象的“組合”得來的,這讓程序更加的靈活)

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