一、策略模式概述
模式定義: 定義算法族,分別封裝一起,讓它們可以相互替換;此模式讓算法的變化獨(dú)立于使用它的客戶
使用場(chǎng)景: 針對(duì)一個(gè)問題有多種解決方法,而區(qū)別僅僅在于算法(行為)不同
模式結(jié)構(gòu):
1.抽象策略類
定義了一個(gè)公共接口,各種不同的算法以不同的方式實(shí)現(xiàn)這個(gè)接口,環(huán)境角色使用這個(gè)接口調(diào)用不同的算法,一般使用接口或抽象類實(shí)現(xiàn)。
2.具體策略類
實(shí)現(xiàn)了抽象策略定義的接口,提供具體的算法實(shí)現(xiàn)。
3.環(huán)境類
持有一個(gè)抽象策略類的引用,最終給客戶端調(diào)用。
UML圖:

二、標(biāo)準(zhǔn)策略代碼實(shí)現(xiàn)
/**
* 抽象策略類
*/
public interface IStrategy {
int calculate(int num1, int num2);
}
/**
* 具體實(shí)現(xiàn)類A
*/
public class AddStrategy implements IStrategy {
@Override
public int calculate(int num1, int num2) {
System.out.println("加法");
return num1 + num2;
}
}
/**
* 具體實(shí)現(xiàn)類B
*/
public class MinusStrategy implements IStrategy {
@Override
public int calculate(int num1, int num2) {
System.out.println("減法");
return num1 - num2;
}
}
/**
* 環(huán)境類(持有策略抽象類)
*/
public class Context {
private IStrategy cal;
public Context(IStrategy cal) {
this.cal = cal;
}
public int excuteCalculate(int num1, int num2) {
return cal.calculate(num1, num2);
}
}
測(cè)試結(jié)果
public class ClientMain {
public static void main(String[] args) {
Context context = new Context(new AddStrategy());
int result = context.excuteCalculate(30, 20);
System.out.println(result);
}
}
三、模式理解重點(diǎn)
策略模式的重心不是如何實(shí)現(xiàn)算法,而是如何組織這些算法,從而讓程序結(jié)構(gòu)更加靈活,具有更好的維護(hù)性和擴(kuò)展性。
判斷是不是策略模式,只要看一個(gè)類里是否持有了抽象對(duì)象的關(guān)聯(lián)或者依賴,且當(dāng)客戶使用這個(gè)類使用實(shí)例化了這個(gè)屬性。
四、策略模式j(luò)ava用例
1.Comparator的使用
java中比較的使用就是典型的策略模式,我們實(shí)例化了Comparator(抽象策略類)接口傳遞給TreeSet(環(huán)境類)。
TreeSet<Person> treeSet=new TreeSet<>(new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
查看源碼可以發(fā)現(xiàn)TreeSet間接持有了Comparator對(duì)象
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
}
public class TreeMap<K,V> extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
private final Comparator<? super K> comparator;
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
}
2.Arrays.sort()中Comparator的使用
Arrays.sort(null, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
查看源碼可以發(fā)現(xiàn)Arrays雖然沒有持有Comparator對(duì)象,而是通過靜態(tài)方法執(zhí)行,但是思想上還是使用策略模式
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
五、變通
根據(jù)實(shí)際使用策略模式也并非一成不變,只要是使用了策略思想都可以歸為該模式;下面這種方式是環(huán)境類持有抽象類的依賴。
/**
* 環(huán)境類(持有策略抽象類)
*/
public class Context {
public static int excuteCal(IStrategy cal,int num1,int num2){
return cal.calculate(num1,num2);
}
}
**測(cè)試結(jié)果**
public class ClientMain {
public static void main(String[] args) {
int result = Context.excuteCal(new AddStrategy(),30,20);
System.out.println(result);
}
}
//TODO
六、心得參考
http://c.biancheng.net/view/1378.html
https://blog.csdn.net/u012124438/article/details/70039943/
HeadFirst設(shè)計(jì)模式