“策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于算法的客户”
场景:
一个基类有很多个子类,现在他们需要实现一个共同的函数,凡是各个子类的实现可能各有不同,这时候应该怎么办?
思路1:把这个函数写在基类里,然后子类去根据自己的需要重写这个函数
好处:代码可以复用,对应了设计原则“找出应用中可能变化之处,把它独立出来,不要和那些不变的代码混在一起”
坏处:可能会有子类不小心忘了写了,就直接继承了基类的实现,这样的错误比较难查
思路2:直接把这个方法做成接口放到基类里,然后子类去实现
好处:代码的灵活性很好,各个子类修改自己的方法不会影响别人,对应了设计原则“多用组合 少用继承”
坏处:代码无法复用
所以,这两者扬长避短,形成了一个这样的解决思路:
1. 先一个新的接口,用来解决问题,然后做出它的实现一系列。
2. 在父类里实例化一个这个接口。然后在那个函数里调用这个接口的方法解决问题
3.子类为这个接口选择实现
这就等于把这个函数的实现委托给了另一个类,两个类组合起来解决问题,“多用组合 少用继承”
标准实现
基类:
public abstract class Base { protect Behavior beh; public Base() { } protect void setBehavior(Behavior beh) { this.beh = ben; } public void performBehavior() { if (beh != null) { beh.doIt(); } } }
子类
public class Child extends Base { public Child() { Behavior beh = new Behavior1(); setBehavior(h); } }
委托接口:
public interface Behavior { public void doIt(); }
委托接口实现1
public class Behavior1 implements Behavior { public void doIt() { //具体实现 } }
android应用实例
google Volley
Volley中的每个网络请求被封装成了一个类,他们共同继承自基类Request,Request的子类有JsonObjectRequest, ImageRequest等。他们都需要一个网络重连的算法。
所以google写了一个这个算法的接口
/** * Retry policy for a request. */ public interface RetryPolicy { /** * Returns the current timeout (used for logging). */ public int getCurrentTimeout(); /** * Returns the current retry count (used for logging). */ public int getCurrentRetryCount(); /** * Prepares for the next retry by applying a backoff to the timeout. * @param error The error code of the last attempt. * @throws VolleyError In the event that the retry could not be performed (for example if we * ran out of attempts), the passed in error is thrown. */ public void retry(VolleyError error) throws VolleyError; }
它的实现有DefaultRetryPolicy等
这里是个十分标准的策略模式
在Request基类中有一个成员变量
private RetryPolicy mRetryPolicy;
同时也有一个set方法
/** * Sets the retry policy for this request. * * @return This Request object to allow for chaining. */ public Request<?> setRetryPolicy(RetryPolicy retryPolicy) { mRetryPolicy = retryPolicy; return this; }
然后在初始化Request的时候调用了这个set方法,把适当的重联算法装配进去
public Request(int method, String url, Response.ErrorListener listener) { mMethod = method; mUrl = url; mErrorListener = listener; setRetryPolicy(new DefaultRetryPolicy()); //这个是基类,因此放了一个默认的方法进去 mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode(); } public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight, Config decodeConfig, Response.ErrorListener errorListener) { super(Method.GET, url, errorListener); setRetryPolicy( new DefaultRetryPolicy(IMAGE_TIMEOUT_MS, IMAGE_MAX_RETRIES, IMAGE_BACKOFF_MULT)); //这个是子类,为其选择了特殊的重联算法 mListener = listener; mDecodeConfig = decodeConfig; mMaxWidth = maxWidth; mMaxHeight = maxHeight; }