您的位置:首页 > 大数据 > 人工智能

职责链模式(Chain Of Responsibility)

2016-07-19 12:33 411 查看

1. 模式的定义

考虑这样一个功能:申请聚餐费用的管理,对于聚餐费用的申请,要求处理的逻辑步骤是灵活的。

客户端发出一个请求,会有很多对象都可以处理这个请求,而且不同的对象的处理逻辑是不一样的。对于客户端而言,无所谓谁来处理,反正有对象处理就可以。而且在上述流程中,还希望处理流程是可以灵活变动的,而处理请求的对象需要能方便地修改或者被替换掉,以适应新的业务功能的需要。

职责链模式的定义:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

2. UML图



Handler:定义职责的接口,通常在这里定义处理请求的方法

ConcreteHandler:实现职责的类,在这个类中,对在它职责范围内请求的处理,如果不处理,就继续转发请求给后继者

Client:职责链的客户端,向链上的具体处理对象提交请求,让职责链负责处理

代码:

/**
* 定义职责对象的接口
*/
public abstract class Handler {
/**
* 持有下一个处理请求的对象
*/
protected Handler successor = null;
/**
* 设置下一个处理请求的对象
* @param successor 下一个处理请求的对象
*/
public void setSuccessor(Handler successor){
this.successor = successor;
}
/**
* 处理聚餐费用的申请
* @param user 申请人
* @param fee 申请的钱数
* @return 成功或失败的具体通知
*/
public abstract String handleFeeRequest(String user, double fee);
}

public class ProjectManager extends Handler{

public String handleFeeRequest(String user, double fee) {
String str = "";
//项目经理的权限比较小,只能在500以内
if(fee < 500){
//为了测试,简单点,只同意小李的
if("小李".equals(user)){
str = "项目经理同意"+user+"聚餐费用"+fee+"元的请求";
}else{
//其他人一律不同意
str = "项目经理不同意"+user+"聚餐费用"+fee+"元的请求";
}
return str;
}else{
//超过500,继续传递给级别更高的人处理
if(this.successor!=null){
return successor.handleFeeRequest(user, fee);
}
}
return str;
}
}

public class DepManager extends Handler{

public String handleFeeRequest(String user, double fee) {
String str = "";
//部门经理的权限只能在1000以内
if(fee < 1000){
//为了测试,简单点,只同意小李申请的
if("小李".equals(user)){
str = "部门经理同意"+user+"聚餐费用"+fee+"元的请求";
}else{
//其他人一律不同意
str = "部门经理不同意"+user+"聚餐费用"+fee+"元的请求";
}
return str;
}else{
//超过1000,继续传递给级别更高的人处理
if(this.successor!=null){
return this.successor.handleFeeRequest(user, fee);
}
}
return str;
}

}

public class GeneralManager extends Handler{
public String handleFeeRequest(String user, double fee) {
String str = "";
//总经理的权限很大,只要请求到了这里,他都可以处理
if(fee >= 1000){
//为了测试,简单点,只同意小李的
if("小李".equals(user)){
str = "总经理同意"+user+"聚餐费用"+fee+"元的请求";
}else{
//其他人一律不同意
str = "总经理不同意"+user+"聚餐费用"+fee+"元的请求";
}
return str;
}else{
//如果还有后继的处理对象,继续传递
if(this.successor!=null){
return successor.handleFeeRequest(user, fee);
}
}
return str;
}

}

public class Client {
public static void main(String[] args) {
//先要组装职责链
Handler h1 = new GeneralManager();
Handler h2 = new DepManager();
Handler h3 = new ProjectManager();
h3.setSuccessor(h2);
h2.setSuccessor(h1);

//开始测试
String ret1 = h3.handleFeeRequest("小李", 300);
System.out.println("the ret1="+ret1);
String ret2 = h3.handleFeeRequest("小张", 300);
System.out.println("the ret2="+ret2);

String ret3 = h3.handleFeeRequest("小李", 600);
System.out.println("the ret3="+ret3);
String ret4 = h3.handleFeeRequest("小张", 600);
System.out.println("the ret4="+ret4);

String ret5 = h3.handleFeeRequest("小李", 1200);
System.out.println("the ret5="+ret5);
String ret6 = h3.handleFeeRequest("小张", 1200);
System.out.println("the ret6="+ret6);
}
}


3. 研磨设计模式

在标准的职责链中,只要有对象处理了请求,这个请求就到此为止,不再被传递和处理了。如果要变形使用职责链,就可以让这个请求继续传递,每个职责对象对这个请求进行一定的功能处理,从而形成一个处理请求的功能链。

1) 处理多种请求

- 不同的业务需要传递的业务数据不同

- 不同的业务请求的方法不同

/**
* 通用的请求对象
*/
public class RequestModel {
/**
* 表示具体的业务类型
*/
private String type;
/**
* 通过构造方法把具体的业务类型传递进来
* @param type 具体的业务类型
*/
public RequestModel(String type){
this.type = type;
}
public String getType() {
return type;
}
}

/**
* 定义职责对象的接口
*/
public abstract class Handler {
/**
* 持有下一个处理请求的对象
*/
protected Handler successor = null;
/**
* 设置下一个处理请求的对象
* @param successor 下一个处理请求的对象
*/
public void setSuccessor(Handler successor){
this.successor = successor;
}
/**
* 通用的请求处理方法
* @param rm 通用的请求对象
* @return 处理后需要返回的对象
*/
public Object handleRequest(RequestModel rm){
if(successor != null){
//这个是默认的实现,如果子类不愿意处理这个请求,那就传递到下一个职责对象去处理
return this.successor.handleRequest(rm);
}else{
System.out.println("没有后续处理或者暂时不支持这样的功能处理");
return false;
}
}
}

/**
* 封装跟聚餐费用申请业务相关的请求数据
*/
public class FeeRequestModel extends RequestModel{
/**
* 约定具体的业务类型
*/
public final static String FEE_TYPE = "fee";
public FeeRequestModel() {
super(FEE_TYPE);
}
/**
* 申请人
*/
private String user;
/**
* 申请金额
*/
private double fee;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public double getFee() {
return fee;
}
public void setFee(double fee) {
this.fee = fee;
}
}

/**
* 实现项目经理处理聚餐费用申请的对象
*/
public class ProjectManager extends Handler{
public Object handleRequest(RequestModel rm){
if(FeeRequestModel.FEE_TYPE.equals(rm.getType())){
//表示聚餐费用申请
return handleFeeRequest(rm);
}else{
//其他的项目经理暂时不想处理
return super.handleRequest(rm);
}
}
private Object handleFeeRequest(RequestModel rm) {
//先把通用的对象造型回来
FeeRequestModel frm = (FeeRequestModel)rm;
String str = "";
//项目经理的权限比较小,只能在500以内
if(frm.getFee() < 500){
//为了测试,简单点,只同意小李的
if("小李".equals(frm.getUser())){
str = "项目经理同意"+frm.getUser()+"聚餐费用"+frm.getFee()+"元的请求";
}else{
//其他人一律不同意
str = "项目经理不同意"+frm.getUser()+"聚餐费用"+frm.getFee()+"元的请求";
}
return str;
}else{
//超过500,继续传递给级别更高的人处理
if(this.successor != null){
return successor.handleRequest(rm);
}
}
return str;
}
}

/**
* 封装跟预支差旅费申请业务相关的请求数据
*/
public class PreFeeRequestModel extends RequestModel{
/**
* 约定具体的业务类型
*/
public final static String FEE_TYPE = "preFee";
public PreFeeRequestModel() {
super(FEE_TYPE);
}
/**
* 申请人
*/
private String user;
/**
* 申请金额
*/
private double fee;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public double getFee() {
return fee;
}
public void setFee(double fee) {
this.fee = fee;
}
}

/**
* 实现为项目经理增加预支差旅费用申请处理的功能的子对象,
* 现在的项目经理既可以处理聚餐费用申请,又可以处理预支差旅费用申请
*/
public class ProjectManager2 extends ProjectManager{
public Object handleRequest(RequestModel rm){
if(PreFeeRequestModel.FEE_TYPE.equals(rm.getType())){
//表示预支差旅费用申请
return myHandler(rm);
}else{
//其他的让父类去处理
return super.handleRequest(rm);
}
}
private Object myHandler(RequestModel rm) {
//先把通用的对象造型回来
PreFeeRequestModel frm = (PreFeeRequestModel)rm;
//项目经理的权限比较小,只能在5000以内
if(frm.getFee() < 5000){
//工作需要嘛,统统同意
System.out.println("项目经理同意"+frm.getUser()+"预支差旅费用"+frm.getFee()+"元的请求");
return true;
}else{
//超过5000,继续传递给级别更高的人处理
if(this.successor!=null){
return this.successor.handleRequest(rm);
}
}
return false;
}
}

public class Client {
public static void main(String[] args) {
//DepManager的实现与ProjectManager类似
//DepManager2的实现与ProjectManager2类似

//先要组装职责链
Handler h1 = new GeneralManager2();
Handler h2 = new DepManager2();
Handler h3 = new ProjectManager2();
h3.setSuccessor(h2);
h2.setSuccessor(h1);

//开始测试申请聚餐费用
FeeRequestModel frm = new FeeRequestModel();
frm.setFee(300);
frm.setUser("小李");
//调用处理
String ret1 = (String)h3.handleRequest(frm);
System.out.println("ret1="+ret1);

//重新设置申请金额,再调用处理
frm.setFee(800);
h3.handleRequest(frm);
String ret2 = (String)h3.handleRequest(frm);
System.out.println("ret2="+ret2);

//重新设置申请金额,再调用处理
frm.setFee(1600);
h3.handleRequest(frm);
String ret3 = (String)h3.handleRequest(frm);
System.out.println("ret3="+ret3);

//开始测试申请预支差旅费用
PreFeeRequestModel pfrm = new PreFeeRequestModel();
pfrm.setFee(3000);
pfrm.setUser("小张");
//调用处理
h3.handleRequest(pfrm);
//重新设置申请金额,再调用处理
pfrm.setFee(6000);
h3.handleRequest(pfrm);
//重新设置申请金额,再调用处理
pfrm.setFee(36000);
h3.handleRequest(pfrm);
}
}


2) 功能链

每个职责对象负责处理请求的某一方面的功能,处理完成后,不是停止,而是继续向下传递请求。

/**
* 封装销售单的数据,简单的示意一些
*/
public class SaleModel {
/**
* 销售的商品
*/
private String goods;
/**
* 销售的数量
*/
private int saleNum;
public String getGoods() {
return goods;
}
public void setGoods(String goods) {
this.goods = goods;
}
public int getSaleNum() {
return saleNum;
}
public void setSaleNum(int saleNum) {
this.saleNum = saleNum;
}

public String toString(){
return "商品名称="+goods+",销售数量="+saleNum;
}
}

/**
* 定义职责对象的接口
*/
public abstract class SaleHandler {
/**
* 持有下一个处理请求的对象
*/
protected SaleHandler successor = null;
/**
* 设置下一个处理请求的对象
* @param successor 下一个处理请求的对象
*/
public void setSuccessor(SaleHandler successor){
this.successor = successor;
}
/**
* 处理保存销售信息的请求
* @param user 操作人员
* @param customer 客户
* @param saleModel 销售数据
* @return 是否处理成功
*/
public abstract boolean sale(String user,String customer,SaleModel saleModel);
}

/**
* 进行权限检查的职责对象
*/
public class SaleSecurityCheck extends SaleHandler{
public boolean sale(String user, String customer, SaleModel saleModel) {
//进行权限检查,简单点,就小李能通过
if("小李".equals(user)){
return this.successor.sale(user, customer, saleModel);
}else{
System.out.println("对不起"+user+",你没有保存销售信息的权限");
return false;
}
}
}

/**
* 进行数据通用检查的职责对象
*/
public class SaleDataCheck extends SaleHandler{
public boolean sale(String user, String customer, SaleModel saleModel) {
//进行数据通用检查,稍麻烦点,每个数据都要检测
if(user==null || user.trim().length()==0){
System.out.println("申请人不能为空");
return false;
}
if(customer==null || customer.trim().length()==0){
System.out.println("客户不能为空");
return false;
}
if(saleModel==null ){
System.out.println("销售商品的数据不能为空");
return false;
}
if(saleModel.getGoods()==null ||saleModel.getGoods().trim().length()==0){
System.out.println("销售的商品不能为空");
return false;
}
if(saleModel.getSaleNum()==0){
System.out.println("销售商品的数量不能为0");
return false;
}
//如果通过了上面的检测,那就向下继续执行
return this.successor.sale(user, customer, saleModel);
}
}

/**
* 进行数据逻辑检查的职责对象
*/
public class SaleLogicCheck extends SaleHandler{
public boolean sale(String user, String customer, SaleModel saleModel) {
//进行数据的逻辑检查,比如检查ID的唯一性,主外键的对应关系等等
//这里应该检查这种主外键的对应关系,比如销售商品是否存在
//为了演示简单,直接通过吧

//如果通过了上面的检测,那就向下继续执行
return this.successor.sale(user, customer, saleModel);
}
}

/**
* 真正处理销售的业务功能的职责对象
*/
public class SaleMgr extends SaleHandler{
public boolean sale(String user, String customer, SaleModel saleModel) {
//进行真正的业务逻辑处理
System.out.println(user+"保存了"+customer+"购买 "+saleModel+" 的销售数据");
return true;
}
}

/**
* 商品销售管理模块的业务处理
*/
public class GoodsSaleEbo {
/**
* 保存销售信息,本来销售数据应该是多条,太麻烦了,为了演示,简单点
* @param user 操作人员
* @param customer 客户
* @param saleModel 销售数据
* @return 是否保存成功
*/
public boolean sale(String user,String customer,SaleModel saleModel){
//如果全部在这里处理,基本的顺序是
//1:权限检查
//2:通用数据检查(这个也可能在表现层已经作过了)
//3:数据逻辑校验
//4:真正的业务处理

//但是现在通过功能链来做,这里就主要负责构建链
SaleSecurityCheck ssc = new SaleSecurityCheck();
SaleDataCheck sdc = new SaleDataCheck();
SaleLogicCheck slc = new SaleLogicCheck();
SaleMgr sd = new SaleMgr();
ssc.setSuccessor(sdc);
sdc.setSuccessor(slc);
slc.setSuccessor(sd);
//向链上的第一个对象发出处理的请求
return ssc.sale(user, customer, saleModel);
}
}

public class Client {
public static void main(String[] args) {
//创建业务对象
GoodsSaleEbo ebo = new GoodsSaleEbo();
//准备测试数据
SaleModel saleModel = new SaleModel();
saleModel.setGoods("张学友怀旧经典");
saleModel.setSaleNum(10);

//调用业务功能
ebo.sale("小李", "张三", saleModel);
ebo.sale("小张", "李四", saleModel);
}
}


3)职责链的本质:分离职责,动态组合
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: