利用责任链模式实现加载不同来源的数据

在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。
责任链模式是一种对象的行为模式,在责任链模式中每个对象及其下家的引用而形成一条链,请求在这个链式传递,直到链上的某个对象处理此请求。责任链模式非常适合移动端先从内存中加载数据,如果内存中没有则去硬盘中加载,最后再通过网络加载数据,这篇文章将介绍利用责任链模式来解决这个问题。

责任链模式简单介绍

首先简单介绍一下责任链模式,责任链模式的思想及其作用在前面已经介绍过了,这里首先通过下图对责任链模式做个简单了解。
index.png

下面简单介绍一下图中的角色。
Handler:处理请求的接口,可以由接口或抽象类来实现。在Handler中handleRequest是处理请求的方法,successor是其的下家引用。
ConcreteHandler是Handler的具体实现。
责任链模式的具体实现这里就不做介绍了,大家可以通过其他途径了解。下面就是我们项目中的应用了。

项目中的具体实现

我们的需求可以由下面的流程图来概括。要实现这样的需求我们应该怎么做呢?if,else太low,这就是我们的责任链模式的用武之地。
flow.png

首先是handler的定义,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class BaseHandler {
// 持有后继的责任对象
protected BaseHandler successor;
// 示意处理请求的方法,虽然这个示意方法是没有传入参数的
//但实际是可以传入参数的,根据具体需要来选择是否传递参数
public abstract void handleRequest(CallBack callBack);

// 取值方法
public BaseHandler getSuccessor() {
return successor;
}

// 赋值方法,设置后继的责任对象

public void setSuccessor(BaseHandler successor) {
this.successor = successor;
}
}

其中的CallBack是项目中自己封装的,大家可以自行替换。
接下来是DiskTodayRecommendHandler,这是BaseHandler的具体实现者,这个类将会向硬盘请求数据。

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
50
51
52
53
54
55
public class DiskTodayRecommendHandler extends BaseHandler {
private HistoryDateBiz mHistoryDateBiz;

public DiskTodayRecommendHandler() {
setSuccessor(new NetTodayRecommendHandler());
mHistoryDateBiz = new HistoryDateBizImpl();
}

@Override
public void handleRequest(final CallBack callBack) {
final long savedUpdateDate = SPUtil.readLong(Constant.SP_KEY_UPDATE_DATE);

CallBack<HttpResult<String>> historyCallBack = new CallBack<HttpResult<String>>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {
List<DryGoods> dryGoodses = DaoWrapper.query(DateUtil.parse(savedUpdateDate));
if (dryGoodses != null && dryGoodses.size() > 0) {
callBack.onNext(TodayResult.build(dryGoodses));
}else {
getSuccessor().handleRequest(callBack);
}
}

@Override
public void onNext(HttpResult<String> stringHttpResult) {
//请求是否更新数据出错
if (stringHttpResult == null || stringHttpResult.results == null || stringHttpResult.results.size() < 0) {
getSuccessor().handleRequest(callBack);
} else {
//将请求传递到下家
getSuccessor().handleRequest(callBack);
}
}
};

if (DateUtil.today() <= savedUpdateDate) {
//没有更新
List<DryGoods> dryGoodses = DaoWrapper.query(DateUtil.parse(savedUpdateDate));
if (dryGoodses != null && dryGoodses.size() > 0) {
callBack.onNext(TodayResult.build(dryGoodses));
}else {
getSuccessor().handleRequest(callBack);
}
} else {
mHistoryDateBiz.loadHistoryDate(historyCallBack);
}

}

}

HistoryDateBiz是用来请求数据判断数据是否有更新。接下来是网络请求handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class NetTodayRecommendHandler extends BaseHandler {
@Override
public void handleRequest(CallBack callBack) {
Date date = DateUtil.parse(SPUtil.readLong(Constant.SP_KEY_UPDATE_DATE));
Calendar ca = Calendar.getInstance();
ca.setTime(date);
int year = ca.get(Calendar.YEAR);
int month = ca.get(Calendar.MONTH) + 1;
int day = ca.get(Calendar.DAY_OF_MONTH);

HttpProvider<TodayRecommendService> httpProvider = HttpProvider.getInstance();
TodayRecommendService todayRecommendService = httpProvider.getService(Url.URL_DAY, TodayRecommendService.class);
ApiProvider<TodayResult.TodayRecommend> apiProvider = ApiProvider.getInstance();
apiProvider.executeTodayRecommend(todayRecommendService.loadTodayDryGoods(year, month, day), callBack);
}
}

以上就是我们利用责任链模式实现从多个来源请求数据的示例!全部代码可去这里查看。