--------------------------------------------------根據《Head First 設計模式》整理記憶--------------------------------------------------------------------
從一個添加鴨子的行爲講起,一開始採用的是繼承:
DUCK父類:
<span style="font-size:14px;">package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 創建時間:2015年7月8日 上午10:37:42 類說明
*/
public class Duck {
public void quack() {
System.out
.println("-------------------Duck quack-----------------------");
}
public void swim() {
System.out
.println("-------------------Duck swim----------------------");
}
public void display() {
System.out
.println("-------------------Duck display-------------------");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
</span>
MallardDuck子類:
<span style="font-size:14px;">package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 創建時間:2015年7月8日 上午10:40:05 類說明
*/
public class MallardDuck extends Duck {
public void display() {
System.out
.println("-------------------------MallardDuck display---------------------------");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
</span>
ReadheadDuck子類:
<span style="font-size:14px;">package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 創建時間:2015年7月8日 上午10:41:13 類說明
*/
public class RedheadDuck extends Duck{
public void display() {
System.out
.println("-------------------------RedheadDuck display---------------------------");
}
public static void main(String[] args) {
RedheadDuck aRedheadDuck = new RedheadDuck();
aRedheadDuck.quack();
}
}
</span>
法一:後來需要添加一個fly行爲,首先想到的是直接在父類裏面添加fly方法,課本上說造成了滿屏飛的鴨子(PS:這個我們一般不會犯這個錯誤,子類需要Override一下的)
如同dispal一樣去實現這個行爲:
缺點:
1.代碼在多個子類重複;
2.運行時的行爲不容易改變;
3.很難知道所有鴨子的行爲;
4.改變會牽一髮而動全身;
法二:MallardDuck繼承Duck父類,然後實現Flyable接口,當鴨子種類很多時候噩夢發生,有很多的鴨子的飛行行爲是相通的;
設計原則一:
找出其中可能需要變化之處,把他們獨立出來,不要和那些需要變化的代碼混在一起。
設計原則二:
針對接口編程,而不是針對實現編程。---關鍵在於利用多態---
法三:測試Duck的代碼:
Duck類有兩個行爲類接口的引用:
package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 創建時間:2015年7月8日 上午10:37:42 類說明
*/
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void swim() {
System.out
.println("-------------------Duck swim----------------------");
}
public void display() {
System.out
.println("-------------------Duck display-------------------");
}
public void performQuack() {//委託給行爲類
quackBehavior.quack();
}
public void performFly() {//委託給行爲類
flyBehavior.fly();
}
}
兩個接口及其實現類爲:
第一個飛行接口及其實現:
public interface FlyBehavior {
public void fly();
}
public class FlyNoWay {
<span style="white-space:pre"> </span>public void fly() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------I can't fly-------------------");
<span style="white-space:pre"> </span>}
}
public class FlyWithWings implements FlyBehavior {
<span style="white-space:pre"> </span>public void fly() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------FlyWithWings-------------------");
<span style="white-space:pre"> </span>}
}
第一個鴨子叫接口及其實現:
public interface QuackBehavior {
public void quack();
}
public class MuteQuack implements QuackBehavior{
<span style="white-space:pre"> </span>public void quack() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------MuteQuack----------------------");
<span style="white-space:pre"> </span>}
}
public class Quack implements QuackBehavior {
<span style="white-space:pre"> </span>public void quack() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------quack----------------------");
<span style="white-space:pre"> </span>}
}
public class Squeak implements QuackBehavior {
<span style="white-space:pre"> </span>public void quack() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------Squeak----------------------");
<span style="white-space:pre"> </span>}
}
編寫測試用例:
package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 創建時間:2015年7月8日 上午10:40:05 類說明
*/
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display() {
System.out
.println("-------------------MallardDuck display-------------------");
}
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performFly();
mallard.performQuack();
}
}
法四:動態設定行爲,鴨子的行爲可以動態變化的時候,這一秒旋轉飛,下一秒倒着飛,就是這麼任性,怎麼辦,以爲上面已經把鴨子的行爲在構造器內實例化了,需要設置Setter方法去改變。
Duck父類添加兩個方法去改變相應行爲:
public void setQuackBehavior(QuackBehavior qb) {//委託給行爲類
quackBehavior = qb;
}
public void setFlyBehavior(FlyBehavior fb) {//委託給行爲類
flyBehavior = fb;
}
mallardDuck實例進行動態改變自己行爲
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
mallard.setFlyBehavior(new FlyNoWay());
mallard.performFly();
}
最後結果:
-------------------quack----------------------
-------------------FlyWithWings-------------------
-------------------I can't fly-------------------
總結:
策略者模式定義:定義了算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。(這也就是爲什麼圖3中爲何把“行爲”摸去改爲算法的原因)
策略者模式的優點:
1、 提供了一種替代繼承的方法,而且既保持了繼承的優點(代碼重用)還比繼承更靈活(算法獨立,可以任意擴展)。
2、 避免程序中使用多重條件轉移語句,使系統更靈活,並易於擴展。
3、 遵守大部分GRASP原則和常用設計原則,高內聚、低偶合。
策略者模式的缺點:
1、 因爲每個具體策略類都會產生一個新類,所以會增加系統需要維護的類的數量。
ps:GRASP(General Responsibility Assignment Software Pattern)是通用職責軟件分配模式。GRASP的核心是自己幹自己能幹的事,自己只幹自己的 事,也就是職責的分配和實現高內聚。用來解決面向對象設計的一些問題。此外GRASP原則還闡述了幾大原則,以後會繼續寫博道來。
源代碼:http://download.csdn.net/detail/bingbing8219/8879481