定義
策略模式定義了一系列的算法欢顷,并將每一個算法封裝起來槽棍,而且使他們之間可以相互替換,策略模式讓算法獨(dú)立于使它的客戶獨(dú)立而變化
角色
1.環(huán)境(Context)角色
持有一個Strategy的引用2.抽象策略(Strategy)角色
這是一個抽象角色抬驴,通常由一個接口或抽象類實(shí)現(xiàn)炼七。此角色給出所有的具體策略類所需的接口。3.具體策略(ConcreteStrategy)角色
包裝了相關(guān)的算法或行為布持。
需求
假設(shè)現(xiàn)在要一個上商店個搞活動豌拙。 對所有的高級會員打20%的促銷折扣;對中級會員打10%的促銷折扣题暖;對初級會員沒有折扣按傅。
得知算法
算法一:對初級會員沒有折扣。
算法二:對中級會員提供10%的促銷折扣芙委。
算法三:對高級會員提供20%的促銷折扣逞敷。
實(shí)現(xiàn)代碼
抽象策略接口:Strategy
interface IStrategy {
public void doSomething();
}
具體策略1
class ConcreteStrategy1 implements IStrategy {
public void doSomething() {
System.out.println("具體策略1");
}
}
具體策略2
class ConcreteStrategy2 implements IStrategy {
public void doSomething() {
System.out.println("具體策略2");
}
}
策略的上下文,具體的執(zhí)行者:Context
class Context {
private IStrategy strategy;
public Context(IStrategy strategy){
this.strategy = strategy;
}
public void execute(){
strategy.doSomething();
}
}
客戶端
public class Client {
public static void main(String[] args){
Context context;
System.out.println("-----執(zhí)行策略1-----");
context = new Context(new ConcreteStrategy1());
context.execute();
System.out.println("-----執(zhí)行策略2-----");
context = new Context(new ConcreteStrategy2());
context.execute();
}
}
重點(diǎn)
策略模式的重心不是如何實(shí)現(xiàn)算法灌侣,而是如何組織推捐、調(diào)用這些算法,從而讓程序結(jié)構(gòu)更靈活侧啼,具有更好的維護(hù)性和擴(kuò)展性牛柒。
特點(diǎn)
運(yùn)行時策略的唯一性
運(yùn)行期間堪簿,策略模式在每一個時刻只能使用一個具體的策略實(shí)現(xiàn)對象,雖然可以動態(tài)地在不同的策略實(shí)現(xiàn)中切換皮壁,但是同時只能使用一個椭更。
平等性
策略模式一個很大的特點(diǎn)就是各個策略算法的平等性。對于一系列具體的策略算法蛾魄,大家的地位是完全一樣的虑瀑,正因?yàn)檫@個平等性,才能實(shí)現(xiàn)算法之間可以相互替換滴须。所有的策略算法在實(shí)現(xiàn)上也是相互獨(dú)立的舌狗,相互之間是沒有依賴的。
優(yōu)缺點(diǎn)
1.優(yōu)點(diǎn)
策略模式提供了管理相關(guān)的算法族的辦法扔水。策略類的等級結(jié)構(gòu)定義了一個算法或行為族痛侍。恰當(dāng)使用繼承可以把公共的代碼移到父類里面,從而避免代碼重復(fù)魔市。
使用策略模式可以避免使用多重條件(if-else)語句主届。多重條件語句不易維護(hù),它把采取哪一種算法讓子類實(shí)現(xiàn)
2.缺點(diǎn)
客戶端必須知道所有的策略類待德,并自行決定使用哪一個策略類君丁。這就意味著客戶端必須理解這些算法的區(qū)別,以便適時選擇恰當(dāng)?shù)乃惴惏跬Q言之谈截,策略模式只適用于客戶端知道算法或行為的情況。
由于策略模式把每個具體的策略實(shí)現(xiàn)都單獨(dú)封裝成為類涧偷,如果備選的策略很多的話,那么對象的數(shù)目就會很可觀毙死。
注意:和狀態(tài)模式不同的是燎潮,策略模式是客戶端自己定義不同策略,而狀態(tài)模式是內(nèi)部封裝得狀態(tài)扼倘,不同客戶端去設(shè)置具體的狀態(tài)處理确封。
例子
交通工具的收費(fèi):城市乘坐交通工具,打的收費(fèi)標(biāo)準(zhǔn)再菊、公交收費(fèi)標(biāo)準(zhǔn)爪喘、地鐵收費(fèi)標(biāo)準(zhǔn),按照公里來計(jì)算價格纠拔,普通處理就是各種條件判斷秉剑。對于同樣都是收費(fèi)這個計(jì)算,如果將收費(fèi)方法抽象出來稠诲,然后按照不同對象去計(jì)算侦鹏,就會讓代碼顯得沒那么臃腫诡曙,而且維護(hù)起來也很靈活;
將不同收費(fèi)方式放到不同的對象中略水,減少在客戶的判斷計(jì)算
只要告訴用的是什么交通工具价卤,然后點(diǎn)收費(fèi)
方法:
(1)抽象一個收費(fèi)接口
(2)不同交通工具,實(shí)現(xiàn)收費(fèi)計(jì)算
(3)客戶端指明交通工具渊涝,然后調(diào)用收費(fèi)
Android中應(yīng)用
動畫框架
插值器
1.給屬性動畫設(shè)置參數(shù):動畫的作用view慎璧、動畫屬性、動畫起始值和終值跨释、執(zhí)行時間胸私、延遲時間等等,這些數(shù)據(jù)
都封裝到ProtorValusHolder中煤傍。因?yàn)榭赡苁且贿B串動畫盖文,把這些動畫信息放到動畫執(zhí)行隊(duì)列。
而實(shí)際動畫是一楨楨數(shù)據(jù)聯(lián)動起來蚯姆,這里將keyFrame數(shù)據(jù)放到KeyFrameSet(是一個list)五续。
2.動畫執(zhí)行隊(duì)列
線程