Design Patterns in Android:策略模式

前言

剛過去的春節,大家有沒有從“節後綜合徵”中痊癒滿血呢?
新年裏給大家帶來的第一篇是《設計模式Android篇:策略模式》。
點擊此處查看《Design Patterns in Android》系列其他文章。

本文原創作者MichaelX(xiong_it),博客鏈接:http://blog.csdn.net/xiong_it,轉載請註明出處。

策略模式定義

策略模式(Strategy pattern):定義一組算法,將其各個封裝,並且使他們有交換性。

策略模式好處在於使得算法在用戶使用的時候能獨立的改變,單一的修改,並且有良好擴展性。

算法:指的是各個策略的實現邏輯,而非算法領域的數據算法。

策略模式UML類圖

策略模式UML類圖

策略模式各角色講解

  • IStrategy:策略基類(接口或者抽象類),定義子策略需要實現的方法,比如excute(),該方法取決於客戶端代碼(高層代碼)需要該策略實現什麼功能,子類則實現該方法,封裝自己的算法,供外部調用。
  • Context:此Context,非彼(Android中的)Context,它持有IStrategy真實的實例對象,提供給客戶端調用IStrategy時的上下文調度者。
  • ConcreteStrategyA:實現父類IStrategy的方法,封裝自身算法邏輯。
  • ConcreteStrategyB:同上

策略模式的示例代碼

IStrategy

public interface IStrategy {
    void excute();
}

ConcreteStrategyA

public class ConcreteStrategyA implements IStrategy{
    public void excute() {
        System.out.println("1.我是ConcreteStrategyA的算法實現");
    }
}

ConcreteStrategyB

public class ConcreteStrategyB implements IStrategy{
    public void excute() {
        System.out.println("2.我是ConcreteStrategyB的算法實現");
    }
}

Context上下文角色

public class Context {
    private IStrategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void excute() {
        this.strategy.excute();
    }
}

好了,下面是就是客戶端代碼,描述瞭如何使用策略模式
Client

public class Client {
    public static void main(String[] args) {
        Context context;

        context = new Context(new ConcreteStrategyA());
        context.excute();

        // context = new Context(new ConcreteStrategyB());
        // context.excute();
    }
}

如上,客戶端需要什麼策略就new什麼策略,完全取決於客戶端需求,而且如果策略A出現問題,修改策略A就是了,和其他地方完全無關,如果現有策略不符合需求,再實現一個ConcreteStrategyA即可。

Android源碼中的策略模式

大家在使用Animation動畫時,可以給Animation對象設置不同的插值器(Interpolator)來實現動畫快慢速度動態效果。

比如:
LinearInterpolator,線性插值器,實現勻速動畫
AccelerateDecelerateInterpolator:加速減速插值器,實現開始加速,結尾時減速的動畫

BaseInterpolator類:Interpolator的實現類,就是速度插值器策略的基類

/**
 * An abstract class which is extended by default interpolators.
 */
abstract public class BaseInterpolator implements Interpolator {
    private int mChangingConfiguration;
    /**
     * @hide
     */
    public int getChangingConfiguration() {
        return mChangingConfiguration;
    }

    /**
     * @hide
     */
    void setChangingConfiguration(int changingConfiguration) {
        mChangingConfiguration = changingConfiguration;
    }
}

Animation:Context上下文角色

public abstract class Animation implements Cloneable {
    // ...
    // 省略無關代碼
    // ...
    private Interpolator mInterpolator;
    /**
     * Sets the acceleration curve for this animation. Defaults to a linear
     * interpolation.
     *
     * @param i The interpolator which defines the acceleration curve
     * @attr ref android.R.styleable#Animation_interpolator
     */
    public void setInterpolator(Interpolator i) {
        mInterpolator = i;
    }
}

LinearInterpolator等子類就實現了各自速度快慢的算法邏輯

@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }
}

現在,我們給一個ImageView添加View動畫

ImageView view;
Animation animation = getResources().getAnimation(R.anim.pop_anim);
// 給view的動畫設置一個插值器策略
animation.setInterpolator(new LinearInterpolator());
view.startAnimation(animation);

Android開發中的策略模式實踐

需求,現在你開發的Android app需要實現盈利,PM經過一番規劃,想要你接入微信支付支付寶支付,銀聯支付等移動端通用支付方式。

這個功能好實現,接入相關支付SDK即可,問題就在如何優雅的實現這個功能呢?

延伸閱讀:
《 Android App支付系列(一):微信支付接入詳細指南(附官方支付demo)》
《 Android App支付系列(二):支付寶SDK接入詳細指南(附官方支付demo)》

以下是筆者是實現,供各位讀者參考。

  • PayActivity:客戶端角色,支付方式選擇界面
  • AbsPayStrategy:作爲支付策略基類,定義了一個pay方法
  • PayContext:上下文角色,用來封裝支付AbsPayStrategy對象
  • WeChatPayStrategy:封裝了微信支付算法邏輯
  • ALiPayStrategy:封裝了支付寶支付算法邏輯
  • BankCardPayStrategy:封裝了銀行卡支付算法邏輯

支付功能的示意代碼
AbsPayStrategy的實際實現應該爲抽象類,它需要持有Activity對象。

public interface AbsPayStrategy {
    // private Activity mActivity;
    // 本策略主要就是實現支付功能
    void pay();
} 

Context上下文角色

public class PayContext {
    private AbsPayStrategy mPayStrategy;

    public PayContext(AbsPayStrategy payStrategy) {
        mPayStrategy = payStrategy;
    }

    public void pay() {
        mPayStrategy.pay();
    }
}

微信支付策略實現

/**
 * 微信支付策略
 */
public class WeChatPayStrategy implements AbsPayStrategy {

    public void pay() {
        // 此處封裝微信支付邏輯
        // 具體請參考筆者的博文《 Android App支付系列(一):微信支付接入詳細指南(附官方支付demo)》
    }
}

支付寶支付策略實現

/**
 * 支付寶支付策略
 */
public class ALiPayStrategy  implements AbsPayStrategy {

    public void pay() {
        // 此處封裝支付寶支付邏輯
        // 具體請參考筆者的博文《 Android App支付系列(二):支付寶支付SDk接入詳細指南(附官方支付demo)》
    }
}

具體的客戶端代碼,此處爲PayActivity

public class PayActivity extends Activity implements View.OnclickListener{

    private PayContext mPayContext;

    @Override
    public void onClick(View view) {
        switch(v.getId()) {// 客戶端來決定使用哪種支付策略
            case R.id.wechat_pay:
                mPayContext = new PayContext(new WechatPayStrategy());
                break;

            case R.id.wechat_pay:
                mPayContext = new PayContext(new ALiPayStrategy());
                break;

            case R.id.wechat_pay:
                mPayContext = new PayContext(BankCardPayStrategy());
                break;

            default:
                mPayContext = new PayContext(new WechatPayStrategy());
                break;
        }
        // 利用實際的支付策略對象進行支付
        mPayContext.pay();
    } 
}

這樣就實現了一個app內的支付功能,如果微信支付出現問題了,改動微信支付策略代碼,支付寶支付出現問題,改動想要實現即可,職責單一。

如果PM有一天說:我們需要接入百付寶,京東支付。怎麼辦?
簡單啊,實現相應的支付策略即可,完美適應需求變更,實現功能擴展。

總結

如果在開發某功能時,可能出現多種平等的選擇,可以考慮使用策略模式實現。

好了,今天的《設計模式Android篇:策略模式》就到這裏,請繼續關注《Design Patterns in Android》(設計模式Android篇)系列博文,歡迎各位讀者朋友評論區拍磚交流,共同進步。

查看本文最新版本,請進入:MichaelX’s Blog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章