我們?cè)倏匆粋€(gè)策略模式的代碼,深度理解下
//對(duì)象父類,鴨子
public abstract class Duck {
IQuackBehavior quackBehavior; //行為的引用
public abstract void display();
public void performQuack() {
quackBehavior.quack();
}
public void setQuackBehavior(IQuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
//具體的子類,綠頭鴨
public class DuckMallard extends Duck {
@Override
public void display() {
System.out.println("我是 綠頭鴨");
}
}
//行為的接口,叫喊接口
public interface IQuackBehavior {
void quack();
}
//行為實(shí)現(xiàn)1
public class MuteQuack implements IQuackBehavior{
@Override
public void quack() {
System.out.println("不會(huì)發(fā)出聲音");
}
}
//行為實(shí)現(xiàn)2
public class SqueckQuack implements IQuackBehavior {
@Override
public void quack() {
System.out.println("發(fā)出吱吱的聲音");
}
}
//場(chǎng)景驗(yàn)證
public class TestSimulator {
public static void main(String[] args) {
Duck duck = new DuckMallard();
duck.setQuackBehavior(new SqueckQuack());
duck.display();
duck.performQuack();
}
}

上面是headFirst里關(guān)于策略的用例。我們可以一起來(lái)看看代碼為什么這樣寫。
1、找出可能的變化之處,把他們獨(dú)立出來(lái),不要和不變的放在一起。
所以我們可以看出,把display()方法我們放在了父類里,但是卻把叫喊的行為單獨(dú)抽象出來(lái)作為行為類。
因?yàn)閐isplay是所有子類都有的;而叫喊如果放在父類里會(huì)導(dǎo)致子類都要去重寫,有些子類沒(méi)有也要重寫一個(gè)。
這一步我們將行為單獨(dú)出來(lái)了
2、針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程
什么意思呢?以前我們的做法是在父類里定義抽象接口,子類去實(shí)現(xiàn),但是這種方式,我們就被實(shí)現(xiàn)綁的死死的,沒(méi)辦法更改行為。我們?yōu)槭裁床粚⑿袨樵谶\(yùn)行的時(shí)候再給他,還可以讓子類可以改變自己的行為。
這一步我們確定行為使用接口而不是采用繼承和實(shí)現(xiàn)
3、盡可能采用組合,將行為委托到其他類
我們?cè)诟割惱镆昧诵袨榈慕涌谝?,并定義了方法,在方法里通過(guò)引用去調(diào)用對(duì)應(yīng)的行為。
這塊是策略模式變行最多的地方,我們可以有多種方式進(jìn)行引用。第一種通過(guò)構(gòu)造函數(shù),第二種通過(guò)set賦值(同上),第三者可以直接在方法上入?yún)⒁?/p>
//通過(guò)構(gòu)造函數(shù)
public class DuckMallard extends Duck {
public DuckMallard(IQuackBehavior quackBehavior){
this.quackBehavior=quackBehavior;
}
@Override
public void display() {
System.out.println("我是 綠頭鴨");
}
}
public static void main(String[] args) {
Duck duck = new DuckMallard(new SqueckQuack());
duck.display();
duck.performQuack();
}
//通過(guò)方法引用
public abstract class Duck {
public abstract void display();
public void performQuack(IQuackBehavior quackBehavior) {
quackBehavior.quack();
}
}
public static void main(String[] args) {
Duck duck = new DuckMallard();
duck.display();
duck.performQuack(new SqueckQuack());
}
在java里很多時(shí)候策略模式都是這樣用的,直接創(chuàng)建一個(gè)新的策略賦值進(jìn)去
public static void main(String[] args) {
Duck duck = new DuckMallard();
duck.setQuackBehavior(new IQuackBehavior() {
@Override
public void quack() {
System.out.println("我就是這樣叫的");
}
});
duck.display();
duck.performQuack();
}
在策略模式(Strategy Pattern)中,一個(gè)類的行為或其算法可以在運(yùn)行時(shí)更改。這種類型的[設(shè)計(jì)模式]屬于行為型模式。簡(jiǎn)單理解就是一組算法,可以互換,再簡(jiǎn)單點(diǎn)策略就是封裝算法。
模式結(jié)構(gòu)的主要特征
1、有一個(gè)行為接口,同時(shí)還有很多策略實(shí)現(xiàn)
2、持有了抽象接口的引用
策略模式的優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):算法可以隨時(shí)切換,擴(kuò)展性好
缺點(diǎn):策略類會(huì)很多