什么是策略模式?
策略模式定義了算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓算法的變化獨立于使用算法的客戶
設(shè)計原則
- 找出變化之處酥泛,把它們獨立出來
- 針對接口編程,而不是針對實現(xiàn)編程
- 多用組合,少用繼承
模擬鴨子游戲
SimUDuck,游戲中會出現(xiàn)各種鴨子柔袁,一邊游泳戲水呆躲,一邊呱呱叫。
使用面向?qū)ο蟮脑O(shè)計模式:設(shè)計鴨子的超類BaseDuck,并讓各種鴨子繼承此超類
public abstract class BaseDuck {
abstract void display();
}
野鴨子MallardDuck:
public class MallardDuck extends BaseDuck {
void display() {
// 我是綠頭鴨
}
...
}
紅頭鴨子RedheadDuck:
public class RedheadDuck extends BaseDuck {
void display() {
// 我是紅頭鴨子
}
...
}
現(xiàn)在我們的讓鴨子能飛
- 方案一:父類增加
public abstract class BaseDuck {
abstract void display();
public void fly() {
// 飛行,可復(fù)用
};
}
問題:并不是所有的鴨子都能飛
- 方案二:繼承
public abstract class BaseDuck {
abstract void display();
abstract void fly();
}
問題:每個子類都需要重寫, 無法復(fù)用
public class RubberDuck extends BaseDuck {
void display() {
// 橡皮鴨
}
void fly() {
// 覆蓋瘦馍,什么都不做
}
}
public class DecoyDuck extends BaseDuck {
void display() {
// 誘餌鴨
}
void fly() {
// 覆蓋歼秽,什么都不做
}
}
- 方案三:利用接口应役,同時增加鴨子叫接口
public interface Flyable {
fly();
}
public interface Quackable {
quack();
}
public MallardDuck extends BaseDuck implements Flyable, Quackable {
void fly() {
// 翅膀飛行
}
void quack() {
// 呱呱叫
}
}
問題:重復(fù)的代碼越來越多
解決方案
使用設(shè)計原則一:封裝變化
使用設(shè)計原則二:針對接口編程
- 抽取變化部分為接口
public interface FlyBehavior {
void fly();
}
public interface QuackBehavior {
void quack();
}
- 把每個行為實現(xiàn)單獨作為一個類
public class FlyWithWings implments FlyBehavior {
void fly() {
// 使用翅膀飛行
}
}
public class FlyNoWay implments FlyBehavior {
void fly() {
// 什么都不做情组,不會飛!
}
}
public class Quack implments QuackBehavior {
void quack() {
// 鴨子呱呱叫
}
}
public class Squeak implments QuackBehavior {
void quack() {
// 橡皮鴨子吱吱叫
}
}
public class MuteQuack implments QuackBehavior {
void quack() {
// 什么都不做箩祥,不會叫
}
}
- 從新定義鴨子超類
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
void display();
public void performFly(){
if (flyBehavior != null) {
flyBehavior.fly();
}
}
public void performQuack(){
if (quackBehavior != null) {
quackBehavior.quack();
}
}
}
- 定義鴨子的實體類
public class MallardDuck extends BaseQuack {
public MallardDuck() {
// 將鴨子的飛的行為和叫的行為院崇,委托給行為類
flyBehavior = new FlyBehavior();
quackBehavior = new QuackBehavior();
}
void display() {
// 野鴨子
}
}
public class Test {
public static void main(String[] args){
Duck duck = new MallardDuck();
duck.performFly();
duck.performQuack();
}
}
問題:MallardDuck內(nèi)部還是使用了針對實現(xiàn)編程
解決方案
- 在超類鴨子中增加兩個方法
public abstract class Duck {
...
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
- 動態(tài)設(shè)置行為
public class Test {
public static void main(String[] args){
Duck duck = new MallardDuck();
duck.setFlyBehavior(new FlyWithWings());
duck.setQuackBehavior(new Quack());
duck.performFly();
duck.performQuack();
}
}