策略模式-《Head Firsh 設計模式》第一章
阿新 • • 發佈:2019-01-24
本文要點:
- 定義
- 設計原則一:封裝變換部分
- 設計原則二:針對介面程式設計,而不是針對實現程式設計。
- 設計原則三:多用組合,少用繼承。
- 例項:鴨子與行為
策略模式(Strategy Pattern)
一、定義
策略模式定義了演算法組,分別封裝起來,讓他們之間可以相互替換。此模式讓演算法族的變換獨立於使用該演算法的客戶。
二、設計原則一:封裝變換部分
找出可能變換的部分,將其獨立,使得某些部分的變化不會影響到其他部分。將這些變換的部分(例如行為)分離出來,組成一類。
三、設計原則二:針對介面程式設計,而不是針對實現程式設計。
用行為類去實現行為介面,而不是具體子類去實現行為介面。
針對介面程式設計本質是針對超類程式設計。
關鍵在於利用多型
,可以對超類程式設計,在執行時根據具體情況執行行為。
四、例項:鴨子類和行為類
1. 鴨子類
Duke抽象父類,所有的鴨子繼承自父類,在子類裡面實現具體特性,並且設定行為。
public abstract class Duke {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void setFly(FlyBehavior fly) {
flyBehavior = fly;
}
public void setQuack(QuackBehavior quack) {
quackBehavior = quack;
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public abstract String getDescription();
}
//黑色鴨子(用翅膀飛,會叫)
public class BlackDuck extends Duke{
String color = "black";
public BlackDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new QuackCry();
}
public String getDescription() {
return color+" "+flyBehavior.getDescription()+" "+quackBehavior.getDescription();
}
}
//木頭鴨子(不會飛,吱吱叫)
public class WoodDuck extends Duke{
String color = "yellow";
public WoodDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new QuackZhiZhi();
}
public String getDescription() {
return color+" "+flyBehavior.getDescription()+" "+quackBehavior.getDescription();
}
}
2.飛行類(行為類-定義中的演算法族)
//飛行介面
public interface FlyBehavior {
public String getDescription();
public void fly();
}
//具體飛行行為類:不會飛
public class FlyNoWay implements FlyBehavior{
public String getDescription() {
return "fly no way";
}
public void fly() {
System.out.println(getDescription());
}
}
//用翅膀飛
public class FlyWithWings implements FlyBehavior{
public String getDescription() {
return "fly with wings";
}
public void fly() {
System.out.println(getDescription());
}
}
3.鴨叫類
//鴨叫介面
public interface QuackBehavior {
public String getDescription();
public void quack();
}
//正常鴨叫
public class QuackCry implements QuackBehavior{
public String getDescription() {
return "quack cry";
}
public void quack() {
System.out.println(getDescription());
}
}
//吱吱叫
public class QuackZhiZhi implements QuackBehavior{
public String getDescription() {
return "quack zhizhi";
}
public void quack() {
System.out.println(getDescription());
}
}
4.測試
public class testDuck {
public static void main(String[] args) {
Duke duke = new BlackDuck();
System.out.println(duke.getDescription());
duke.performFly();//飛行
duke.performQuack();//鴨叫
duke = new WoodDuck();
System.out.println(duke.getDescription());
duke.performFly();
duke.performQuack();
}
}
執行程式碼:結果正確
black fly with wings quack cry
fly with wings
quack cry
yellow fly no way quack zhizhi
fly no way
quack zhizhi
5.擴充套件新的行為
我們上面實現了策略模式,現在來擴充套件行為體會一下策略模式的便捷。這裡擴充套件一個火箭推進的行為FlyRocketPowered()
,實現`FlyBehavior介面:
public class FlyRocketPowered implements FlyBehavior{
public String getDescription() {
return "fly with Rocket Power!!!";
}
public void fly() {
System.out.println(getDescription());
}
}
給木鴨子改裝火箭推進裝置:
Duke duke = new WoodDuck();
System.out.println(duke.getDescription());
duke.performFly();
duke.performQuack();
duke.setFly(new FlyRocketPowered());//給木鴨子火箭推進器
duke.performFly();
結果:
yellow fly no way quack zhizhi
fly no way
quack zhizhi
fly with Rocket Power!!!
成功的更改為火箭推薦!很方便吧!這就是策略模式更換演算法族(本例中是行為類)的特點,便於擴充套件。
五、設計原則三:多用組合,少用繼承。
1.什麼是組合
像例項中將兩個類組合起來用,這就是組合(Composition)。這種方法和“繼承”的區別在於,鴨子的行為不是繼承而來,而是和適當的行為物件組合而來的。
2.組合的優點
可複用、可擴充套件、可維護
3.繼承提供行為的缺點
- 程式碼在多個子類中重複
- 執行時行為不容易改變
- 難以知道所有行為
- 牽一髮而動全身,造成其他子類不想要的改變。