標籤:new t getc config swa ESS min package default sse
策略模式定義了一些列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變換。
假設我們要出去旅遊,而去旅遊出行的方式有很多,有步行,有坐火車,有坐飛機等等。而如果不使用任何模式,我們的代碼可能就是這樣子的。
public class TravelStrategy { enum Strategy{ WALK,PLANE,SUBWAY } private Strategy strategy; public TravelStrategy(Strategy strategy){ this.strategy=strategy; } public void travel(){ if(strategy==Strategy.WALK){ print("walk"); }else if(strategy==Strategy.PLANE){ print("plane"); }else if(strategy==Strategy.SUBWAY){ print("subway"); } } public void print(String str){ System.out.println("出行旅遊的方式為:"+str); } public static void main(String[] args) { TravelStrategy walk=new TravelStrategy(Strategy.WALK); walk.travel(); TravelStrategy plane=new TravelStrategy(Strategy.PLANE); plane.travel(); TravelStrategy subway=new TravelStrategy(Strategy.SUBWAY); subway.travel(); }}
這樣做有一個致命的缺點,一旦出行的方式要增加,我們就不得不增加新的else if語句,而這違反了物件導向的原則之一,對修改封閉。而這時候,策略模式則可以完美的解決這一切。
首先,需要定義一個策略介面。
public interface Strategy { void travel();}
然後根據不同的出行方式實行對應的介面
public class WalkStrategy implements Strategy{ @Override public void travel() { System.out.println("walk"); }}
public class PlaneStrategy implements Strategy{ @Override public void travel() { System.out.println("plane"); }}
public class SubwayStrategy implements Strategy{ @Override public void travel() { System.out.println("subway"); }}
此外還需要一個封裝策略的類,並調用策略介面中的方法
public class TravelContext { Strategy strategy; public Strategy getStrategy() { return strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void travel() { if (strategy != null) { strategy.travel(); } }}
測試一下代碼
public class Main { public static void main(String[] args) { TravelContext travelContext=new TravelContext(); travelContext.setStrategy(new PlaneStrategy()); travelContext.travel(); travelContext.setStrategy(new WalkStrategy()); travelContext.travel(); travelContext.setStrategy(new SubwayStrategy()); travelContext.travel(); }}
輸出結果如下
planewalksubway
可以看到,應用了策略模式後,如果我們想增加新的出行方式,完全不必要修改現有的類,我們只需要實現策略介面即可,這就是物件導向中的對擴充開放準則。假設現在我們增加了一種單車出行的方式。只需新增一個類即可。
public class BikeStrategy implements Strategy{ @Override public void travel() { System.out.println("bike"); }}
之後設定策略即可
public class Main { public static void main(String[] args) { TravelContext travelContext=new TravelContext(); travelContext.setStrategy(new BikeStrategy()); travelContext.travel(); }}
而在Android的系統源碼中,策略模式也是應用的相當廣泛的.最典型的就是屬性動畫中的應用.
我們知道,在屬性動畫中,有一個東西叫做插值器,它的作用就是根據時間流逝的百分比來來計算出當前屬性值改變的百分比.
我們使用屬性動畫的時候,可以通過set方法對插值器進行設定.可以看到內部維持了一個時間插值器的引用,並設定了getter和setter方法,預設情況下是先加速後減速的插值器,set方法如果傳入的是null,則是線性插值器。而時間插值器TimeInterpolator是個介面,有一個介面繼承了該介面,就是Interpolator這個介面,其作用是為了保持相容
private static final TimeInterpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator(); private TimeInterpolator mInterpolator = sDefaultInterpolator; @Overridepublic void setInterpolator(TimeInterpolator value) { if (value != null) { mInterpolator = value; } else { mInterpolator = new LinearInterpolator(); }}@Overridepublic TimeInterpolator getInterpolator() { return mInterpolator;}
public interface Interpolator extends TimeInterpolator { // A new interface, TimeInterpolator, was introduced for the new android.animation // package. This older Interpolator interface extends TimeInterpolator so that users of // the new Animator-based animations can use either the old Interpolator implementations or // new classes that implement TimeInterpolator directly.}
此外還有一個BaseInterpolator插值器實現了Interpolator介面,並且是一個抽象類別
abstract public class BaseInterpolator implements Interpolator { private int mChangingConfiguration; /** * @hide */ public int getChangingConfiguration() { return mChangingConfiguration; } /** * @hide */ void setChangingConfiguration(int changingConfiguration) { mChangingConfiguration = changingConfiguration; }}
平時我們使用的時候,通過設定不同的插值器,實現不同的動畫速率變換效果,比如線性變換,回彈,自由落體等等。這些都是插值器介面的具體實現,也就是具體的插值器策略。我們略微來看幾個策略。
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; } /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createLinearInterpolator(); }}
public class AccelerateDecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public AccelerateDecelerateInterpolator() { } @SuppressWarnings({"UnusedDeclaration"}) public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator(); }}
內部使用的時候直接調用getInterpolation方法就可以返回對應的值了,也就是屬性值改變的百分比。
Android開發中常見的設計模式(四)——策略模式