行为型模式:类和对象如何交互,划分责任和算法,即对象之间通信。
概念
所谓责任链,多个对象组成一条链,每个对象有其不同的处理逻辑,将一个请求从链的的首端发出,沿着链的路径依次传递给链上的每个对象,直到有对象处理这个请求为止。
使用场景
- 多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定。
- 在请求处理者不明确的情况下向对个对象中的一个提交一个请求。
- 需要动态处理一组对象处理请求。
结构
image.png角色介绍
Handler:抽象处理者角色,声明一个请求处理的方法,并在其中保持一个对下一个处理节点Handler对象的引用。
ConcreteHandler:具体处理者角色,对请求进行处理,如果不能处理则将该请求转发给下一个节点上的处理对象。
实例
简单是实现,这里就不介绍了,网上资源一大把,但是工作中实际很少这样使用,因为很不方便,下面介绍中工作中改造过的责任链模式
- 首先创建一个接口,抽象出链上对象要处理的方法run和直接方法前的资格判断can,如下
/**
* 优惠券发放单元接口
*/
public interface ICouponGrantProcessCell {
/**
* 任务单元名称.
* @return Sting
*
*/
String getName();
/**
* 是否可以运行本任务单元.
* @param param
* @param context
* @return
*/
boolean can(CouponGrantParam param, CouponGrantProcessContext context);
/**
* 执行本任务单元.
* @param param
* @param context
* @return
* @throws Exception
*/
boolean run(CouponGrantParam param, CouponGrantProcessContext context) throws Exception;
}
- 然后新建一个抽象基础类,用来抽象具体处理业务的handler
/**
* 优惠券发放过程单元父类
*/
public abstract class BaseCouponGrantProcessCell implements ICouponGrantProcessCell {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Override
public String getName() {
return getClass().getName();
}
@Override
public boolean can(CouponGrantParam param, CouponGrantProcessContext context) {
return true;
}
@Override
public boolean run(CouponGrantParam param, CouponGrantProcessContext context) throws Exception {
boolean resultFlag = true;
try {
logger.info("\n----开始执行:" + getName());
// 1:子类执行下单过程单元
resultFlag = runing(param, context);
// 2:下面保存日志
////////////////////////
} catch (Exception e) {
logger.error("下单过程执行到" + getName() + "出错", e);
throw new Exception(e);
}
return resultFlag;
}
public abstract boolean runing(CouponGrantParam param, CouponGrantProcessContext context) throws Exception;
}
- 具体业务处理子类1,这里的具体业务不用关心
/**
* 【优惠券发放】参数为空验证
*/
public class ParamEmptyValidateCell extends BaseCouponGrantProcessCell {
@Autowired
private IConsumerService consumerService;
@Autowired
private MarketingActivityService marketingActivityService;
@Autowired
private IStoreService storeService;
@Override
public boolean runing(CouponGrantParam param, CouponGrantProcessContext context) throws Exception {
if (param == null)
throw new BusinessException("【优惠券发放】参数CouponGrantParam不能为空");
if (param.getConsumerId() == null)
throw new BusinessException("【优惠券发放】消费者ID不能为空");
if (param.getActivityId() == null)
throw new BusinessException("【优惠券发放】活动ID不能为空");
if (param.getShopId() == null)
throw new BusinessException("【优惠券发放】ShopId不能为空");
Consumer consumer = consumerService.getConsumerById(param.getConsumerId());
if (null == consumer) {
throw new BusinessException("【优惠券发放】消费者信息不存在");
}
context.setConsumer(consumer);
MarketingActivity marketingActivity = marketingActivityService.getMarketingActivity(param.getActivityId());
if (null == marketingActivity) {
throw new BusinessException("【优惠券发放】营销活动信息不存在");
}
context.setMarketingActivity(marketingActivity);
PointPlace pointPlace = storeService.getStoreByPointId(param.getShopId());
if (null == pointPlace) {
throw new BusinessException("【优惠券发放】店铺信息不存在");
}
context.setPointPlace(pointPlace);
return true;
}
}
具体业务处理子类2
/**
* 【优惠券发放】优惠券发放过程处理
*/
public class CouponGrantCell extends BaseCouponGrantProcessCell {
@Autowired MCouponConsumerService mCouponConsumerService;
@Override
public boolean can(CouponGrantParam param, CouponGrantProcessContext context) {
return param.getWhetherGrant();
}
@Override
public boolean runing(CouponGrantParam param, CouponGrantProcessContext context) throws Exception {
// 最终领取的优惠券信息
List<MCouponConsumer> couponConsumers = new ArrayList<MCouponConsumer>();
PointPlace pointPlace = context.getPointPlace();
// 发放优惠券
List<MarketingActivityCoupon> gettableCoupons = context.getGettableCoupons();
// 生成领取批次,用户单次领取的批次号一致
String getBatch = RandomUtil.getCharAndNumr(16);
gettableCoupons.parallelStream().forEachOrdered(activityCoupon -> {
// 取得此份权益发放张数(打包发放数量)
int packageQty = activityCoupon.getPackageQty();
for (int i = 0; i < packageQty; i++) {
MCouponConsumer mCouponConsumer=mCouponConsumerService.getCouponConsumer(activityCoupon,System.currentTimeMillis());
mCouponConsumer.setConsumerId(param.getConsumerId());
mCouponConsumer.setMarketingActivityId(param.getActivityId());
mCouponConsumer.setMarketingType(1);
mCouponConsumer.setGetBatch(getBatch);
mCouponConsumer.setShopId(pointPlace.getId());
mCouponConsumer.setShopName(pointPlace.getPointName());
mCouponConsumerService.saveMCouponConsumer(mCouponConsumer);
couponConsumers.add(mCouponConsumer);
}
});
context.setCouponConsumers(couponConsumers);
return true;
}
}
- 新建责任链执行过程管理器
/**
* 优惠券发放任务管理器
*/
public class CouponGrantProcess {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
*
*/
private List<ICouponGrantProcessCell> tasks = null;
public void setTasks(List<ICouponGrantProcessCell> tasks) {
Assert.notNull(tasks);
Assert.notEmpty(tasks);
this.tasks = tasks;
logger.info("初始化couponGrantProcess Tasks成功");
}
public void start(CouponGrantParam param, CouponGrantProcessContext context) throws Exception {
for (int index = 0; index < this.tasks.size(); index++) {
ICouponGrantProcessCell task = this.tasks.get(index);
boolean flag = task.can(param, context);
if (flag) {
try {
boolean isNext = task.run(param, context);
if (!isNext) {
break;
}
} catch (Exception e) {
logger.error("终止处理该couponGrantProcess", e);
throw e;
}
}
}
}
}
- xml文件中配置业务类和管理类
- 调用责任链
@Autowired
private CouponGrantProcess couponGrantProcess;
couponGrantProcess.start(param, context);
从改造后的责任链中,可以很明显的看出,链上新添加处理类的话,特别方便,同时,管理起来也很方便。
网友评论