前言
策略模式的主要是定義算法族,分別封裝起來,讓它們之間可以互相替換,使算法的變化獨立於使用算法的客戶。它屬於行爲模式中的一種,我們可以通過一個項目對它進行了解。鴨子項目
一、多種類型鴨子
1.類:鴨子Duck2.行爲:飛fly、叫quack,但是每一種鴨子的行爲不同。
二、兩種方案
1.利用繼承提供Duck行爲這種方式存在一些問題: 代碼在多個子類中重複、運行時行爲不易改變、難知道鴨子的全部行爲、改變會牽一髮動全身,造成其他鴨子不想要的改變。
2.利用接口設計Duck行爲
通過設計FlyBehavior、QuackBehavior接口,將鴨子會飛行和呱呱叫的動作“委託”(delegate)給別人處理,而不是定義在Duck類(或子類)內。
三、代碼實現
1.封裝變化Duck類中的fly/quack會隨着鴨子的不同而改變。將這兩個行爲抽取出來,建立一組新類代表每個行爲。
飛行爲的接口
public interface Flybehavior {
void fly();
}
2.針對接口編程
不針對實現編程,將鴨子的行爲放在分開的類中,此類專門提供某行爲接口的實現,鴨子類不需要知道行爲的實現細節。
具體行爲類
// 不會飛的類
public class FlyNoWay implements Flybehavior {
@Override
public void fly() {
System.out.println("I can't fly!!");
}
}
// 會飛的類
public class FlyWithWings implements Flybehavior {
@Override
public void fly() {
System.out.println("I'm flying!!");
}
}
3.多用組合
少用繼承,鴨子的行爲不是繼承來的,而是和適當的行爲對象組合來的。
public abstract class Duck {
// 行爲接口的引用,具體實現動態生成
public Flybehavior flybehavior;
public Duck(){}
public abstract void display();
public void performFly(){
flybehavior.fly();
}
public void setFlybehavior(Flybehavior flybehavior){
this.flybehavior=flybehavior;
}
}
// 具體的鴨子類
public class MallardDuck extends Duck {
// 構造方法中,動態實現一種行爲類
public MallardDuck(){
flybehavior=new FlyWithWings();
}
@Override
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
// 測試類
public class MainTest {
public static void main(String[] args){
// 鴨子子類
Duck mallard=new MallardDuck();
mallard.performFly();
// 靈活更改鴨子飛的行爲
mallard.setFlybehavior(new FlyNoWay());
mallard.performFly();
mallard.display();
}
}
spring 中的策略模式
1.圖中展示Spring中Bean的實例化過程,其中涉及到接口InstantiationStrategy,用來實例化策略接口類,它定義了三個實例化接口。 2.SimpleInstantiationStrategy實現了該策略,它主要做一些簡單的根據構造函數實例bean的工作,然後CglibSubclassingInstantiationStrategy又繼承了SimpleInstantiationStrategy新增了方法注入方式。3.根據cglib生成代理類實例化方法。在AbstractAutowireCapableBeanFactory中管理了該策略的一個對象,默認是CglibSubclassingInstantiationStrategy策略,運行時候可以通過setInstantiationStrategy改變實例化策略。