android设计模式场景,Android设计模式之策略模式

本文介绍了策略模式的概念,通过Volley网络框架中的RetryPolicy策略来说明其在处理请求重试策略中的应用。Volley的DefaultRetryPolicy作为具体策略实现了超时时间和重试次数的管理,Request类持有RetryPolicy引用并调用其方法。此外,还展示了如何自定义策略以适应不同的业务需求,例如会员折扣策略。策略模式提供了代码的灵活性和可扩展性,避免了条件判断语句,同时允许算法独立于客户端变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天介绍下策略模式

策略模式的概念The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

–(翻译)– 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。

1、需要使用ConcreteStrategy提供的算法。

2、 内部维护一个Strategy的实例。

3、 负责动态设置运行时Strategy具体的实现算法。

4、负责跟Strategy之间的交互和数据传递。

策略模式的组成— Strategy(抽象策略类): 通常由一个接口或者抽象类实现。

— ConcreteStrategy(具体策略角色):包装了相关的算法和行为。一般有多个

— Context(环境角色):持有一个策略类的引用,最终给客户端调用。

策略模式的应用场景定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。实际开发中用途,比如google开源的android网络框架volley,volley的超时重发重发机制就使用到了典型策略模式,看源码

RetryPolicy.java 请求重试策略类,定义了三个接口1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23package com.android.volley;

/**

* 请求重试策略类

* 此类属于抽象策略类对应Strategy

*/

public interface RetryPolicy {

/**

* 超时时间

*/

public int getCurrentTimeout();

/**

* 重试次数

*/

public int getCurrentRetryCount();

/**

* 针对错误异常的处理

*/

public void retry(VolleyError error) throws VolleyError;

}

DefaultRetryPolicy.java 默认重试策略,继承了RetryPolicy ,具体实现了接口,我截取了部分代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31public class DefaultRetryPolicy implements RetryPolicy {

...

public static final int DEFAULT_TIMEOUT_MS = 2500;

private int mCurrentTimeoutMs;

/** The default number of retries */

public static final int DEFAULT_MAX_RETRIES = 0;

/** The default backoff multiplier */

public static final float DEFAULT_BACKOFF_MULT = 1f;

...//代表省略掉的代码

@Override

public int getCurrentTimeout() {

return mCurrentTimeoutMs;

}

@Override

public int getCurrentRetryCount() {

return mCurrentRetryCount;

}

@Override

public void retry(VolleyError error) throws VolleyError {

mCurrentRetryCount++;

mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier);

if (!hasAttemptRemaining()) {

throw error;

}

}

}

Request.java 请求类,持有一个抽象策略类RetryPolicy 的引用,最终给客户端调用。截取部分代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27public abstract class Request implements Comparable> {

private RetryPolicy mRetryPolicy; //持有策略类的引用

...

public Request(int method, String url, Response.ErrorListener listener) {

mMethod = method;

mUrl = url;

mIdentifier = createIdentifier(method, url);

mErrorListener = listener;

setRetryPolicy(new DefaultRetryPolicy());  //设置策略类

mDefaultTrafficStatsTag = findDefaultTrafficStatsTag(url);

}

...

public Request> setRetryPolicy(RetryPolicy retryPolicy) {

mRetryPolicy = retryPolicy;

return this;

}

...

public final int getTimeoutMs() {

return mRetryPolicy.getCurrentTimeout();

}

}

BasicNetwork.java 网络处理类,处理Request,使用到了对应的重试策略,截取部分代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49/**

*遇到异常请求使用到了策略类的getTimeoutMs()方法

*/

private static void attemptRetryOnException(String logPrefix, Request> request,

VolleyError exception) throws VolleyError {

RetryPolicy retryPolicy = request.getRetryPolicy();

int oldTimeout = request.getTimeoutMs();

try {

retryPolicy.retry(exception);

} catch (VolleyError e) {

request.addMarker(

String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));

throw e;

}

request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));

}

...

/**

* 网速慢,获取重试策略的重试次数getCurrentRetryCount

*/

private void logSlowRequests(long requestLifetime, Request> request,

byte[] responseContents, StatusLine statusLine) {

if (DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS) {

VolleyLog.d("HTTP response for request= [lifetime=%d], [size=%s], " +

"[rc=%d], [retryCount=%s]", request, requestLifetime,

responseContents != null ? responseContents.length : "null",

statusLine.getStatusCode(), request.getRetryPolicy().getCurrentRetryCount());

}

}

...

private static void attemptRetryOnException(String logPrefix, Request> request,

VolleyError exception) throws VolleyError {

RetryPolicy retryPolicy = request.getRetryPolicy();

int oldTimeout = request.getTimeoutMs();

try {

retryPolicy.retry(exception);

} catch (VolleyError e) {

request.addMarker(

String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));

throw e;

}

request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));

}

实际使用中,我们可以自定义自己的策略继承RetryPolicy,这样就可以按照我们自己请求策略执行。

下面介绍一个比较简单的实例

自定义简单的策略模式实例

商品实现针对不同等级会员显示对应的会员价,比如一本书原价100元,一级会员打97折,三级会员打8折

PriceStrategy.java,策略类,可以使抽象类或接口,定义算法的公共接口,

1

2

3

4

5

6

7

8/**

* 定义一个计算价格的接口

* 它属于抽象策略类

* @author su

*/

public interface PriceStrategy {

double priceStrategyInterface(double price);

}

SuperVipStrategy.java,超级会员算法,打八折,继承PriceStrategy

1

2

3

4

5

6

7

8

9

10

11

12

13/**

* 超级会员类

* 它属于具体策略类,继承了计算价格接口

* @author su

*

*/

public class SuperVipStrategy implements PriceStrategy {

@Override

public double priceStrategyInterface(double price) {

return price * 0.8; //打八折

}

}

OneVipStrategy.java,一级会员算法,打九七折,继承PriceStrategy

1

2

3

4

5

6

7

8

9

10

11

12/**

* 一级会员类

* 它属于具体策略类

* @author su

*

*/

public class OneVipStrategy implements PriceStrategy {

@Override

public double priceStrategyInterface(double price) {

return 0.97 * price; //打九七折

}

}

ThreeVipStrategy.java,三级会员算法,打九五折,继承PriceStrategy

1

2

3

4

5

6

7

8

9

10

11/**

* 三级会员商品类

* 它属于具体策略类

* @author su

*/

public class ThreeVipStrategy implements PriceStrategy {

@Override

public double priceStrategyInterface(double price) {

return 0.95 * price; //九五折

}

}

Price.java 上下文环境,持有PriceStrategy 的引用。

1

2

3

4

5

6

7

8

9

10

11

12

13

14/**

* 环境角色

* @author su

*

*/

public class Price {

private PriceStrategy priceStrategy;

public Price(PriceStrategy priceStrategy){

this.priceStrategy = priceStrategy;

}

public double getVipPrice(double price){

return priceStrategy.priceStrategyInterface(price);

}

}

测试实例

1

2

3

4

5

6

7

8

9

10

11public class Test {

public static void main(String[] args){

SuperVipStrategy supVipSrategy = new SuperVipStrategy();

OneVipStrategy onVipStrategy = new OneVipStrategy();

System.out.print("超级会员价="+new  Price(supVipSrategy).getVipPrice(100));

System.out.print("一级员价="+new Price(onVipStrategy).getVipPrice(100));

}

}

-----输出结果---

超级会员价=80.0一级员价=97.0

总结

优点1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用),还比继承更灵活(算法独立,可以任意扩展);

2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展;

3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合;

4、 易于进行单元测试,各个算法区分开,可以针对每个算法进行单元测试;

缺点

1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量;

2、 选择何种算法需要客户端来创建对象,增加了耦合,这里可以通过与工厂模式结合解决该问题;

3、 程序复杂化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值