“策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于算法的客户”
场景:
一个基类有很多个子类,现在他们需要实现一个共同的函数,凡是各个子类的实现可能各有不同,这时候应该怎么办?
思路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 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 class Child extends Base {
public Child() {
Behavior beh = new Behavior1();
setBehavior(h);
}
}
委托接口:
- public interface Behavior {
- public void doIt();
- }
public interface Behavior {
public void doIt();
}
委托接口实现1
- public class Behavior1 implements Behavior {
- public void doIt() {
- //具体实现
- }
- }
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;
- }
/**
* 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;
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;
- }
/**
* 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;
- }
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;
}
width="468" height="60" src="http://iam42.iteye.com/iframe_ggbd/187" frameborder="0" scrolling="no">