一. 核心思想
策略模式定義了一系列算法,并將每一個(gè)算法封裝起來(lái),他們之間可以相互切換。
解釋: 同級(jí)的東西可以互相切換.
例如: 現(xiàn)在主流的圖片框架有g(shù)lide、picasso、fresco, 我項(xiàng)目中用的是picasso, 但是我突然想換成glide, 或者后面出來(lái)一個(gè)更牛逼的框架XXX, 代碼要怎么寫(xiě)才能實(shí)現(xiàn)輕松轉(zhuǎn)換呢? 用策略模式就能輕松解決.
二. 簡(jiǎn)單實(shí)現(xiàn)
下面我們以計(jì)算不同交通工具的車(chē)費(fèi)來(lái)簡(jiǎn)單看看策略模式的實(shí)現(xiàn)
public interface IStragety {
/**
* 根據(jù)公里數(shù)計(jì)算價(jià)格
* @param km 公里數(shù)
* @return 價(jià)格
*/
int getPrice(int km);
}
public class StragetyA implements IStragety {
@Override
public int getPrice(int km) {
return km + 10;
}
}
public class StragetyB implements IStragety {
@Override
public int getPrice(int km) {
return km + 20;
}
}
public class ContextStragety {
private IStragety mStragety;
public void setStragety(IStragety stragety) {
mStragety = stragety;
}
public int price(int km) {
return mStragety.getPrice(km);
}
}
使用
ContextStragety contextStragety = new ContextStragety();
// trafficCalculator.setCalculateStragety(new StragetyA());
contextStragety.setStragety(new StragetyB());
int price = contextStragety.calculatePrice(66);
System.out.print("price="+price);
算法可以隨意切換, 符合里氏替換原則.
如果要增加一個(gè)算法, 只需新增一個(gè)子類(lèi)即可, 符合開(kāi)閉原則.
三. 角色劃分
1. 策略的抽象 IStragety
2. 具體的策略實(shí)現(xiàn) StragetyA 和 StragetyB
3. 用來(lái)操作策略的上下文環(huán)境 ContextStragety
四. 優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
① 很好地展示了開(kāi)閉原則和里氏替換原則,
② 算法可以自由切換
③ 避免使用多重條件判斷
④ 耦合低, 擴(kuò)展性良好
缺點(diǎn):
① 隨著策略的增加, 子類(lèi)會(huì)越來(lái)越多
② 所有策略類(lèi)都需要對(duì)外暴露, 也就是"白盒子".
五. 應(yīng)用場(chǎng)景
一個(gè)對(duì)象動(dòng)態(tài)地在幾種算法中選擇一種時(shí)
1. android源碼中.
Animation中的插值器
Animation animation = new AlphaAnimation(1,0);
animation.setInterpolator(new AccelerateDecelerateInterpolator());
2. Java中Comparator.
對(duì)象排序功能實(shí)現(xiàn)
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
public class SortComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
//忽略具體實(shí)現(xiàn)
return 1;
}
}
使用
public static void main(String[] args) {
Student stu[] = {
new Student("張三" ,23),
new Student("李四" ,26)};
Arrays.sort(stu,new SortComparator());
System.out.println(Arrays.toString(stu));
List<Student> list = new ArrayList<>(3);
list.add( new Student("zhangsan" ,31));
list.add( new Student("lisi" ,30));
Collections.sort(list,new SortComparator());
System.out.println(list);
}
只要思想不變, 代碼寫(xiě)法可以隨意改變, 能解決問(wèn)題就OK.