设计模式——责任链模式

责任链模式

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

责任链模式的核心:作为请求者可以不用知道到底是需要谁来处理的(请求者不需要知道处理者是谁)。

责任链模式的重点是在“链”上,“链”是由多个处理者ConcreteHandler组成的,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果。

抽象处理者Handler:

public abstract class Handler { 
    private Handler nextHandler; 
    //每个处理者都必须对请求做出处理
    public final Response handleMessage(Request request){ 
        Response response = null; 
        //判断是否是自己的处理级别 
        if(this.getHandlerLevel().equals(request.getRequestLevel())){ 
            response = this.echo(request); 
        }else{ //不属于自己的处理级别 
            //判断是否有下一个处理者 
            if(this.nextHandler != null){ 
                response = this.nextHandler.handleMessage(request); 
            }else{ 
                //没有适当的处理者,业务自行处理 
            } 
        }
        return response; 
    }
    //设置下一个处理者是谁 
    public void setNext(Handler _handler){ 
        this.nextHandler = _handler; 
    }
    //每个处理者都有一个处理级别 
    protected abstract Level getHandlerLevel(); 
    //每个处理者都必须实现处理任务 
    protected abstract Response echo(Request request); 
}

抽象的处理者实现三个职责:

  • 定义一个请求的处理方法handleMessage,唯一对外开放的方法;
  • 定义一个链的编排方法setNext,设置下一个处理者;
  • 定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别getHandlerLevel和具体的处理任务echo。

具体处理者ConcreteHandler1~3:

public class ConcreteHandler1 extends Handler { 
    //定义自己的处理逻辑 
    protected Response echo(Request request) { 
        //完成处理逻辑 
        return null;
    }
    //设置自己的处理级别 
    protected Level getHandlerLevel() { 
        //设置自己的处理级别 
        return null; 
    } 
}

public class ConcreteHandler2 extends Handler { 
    //定义自己的处理逻辑 
    protected Response echo(Request request) { 
        //完成处理逻辑 
        return null; 
    }
    //设置自己的处理级别 
    protected Level getHandlerLevel() { 
        //设置自己的处理级别 
        return null; 
    } 
}

public class ConcreteHandler3 extends Handler { 
    //定义自己的处理逻辑 
    protected Response echo(Request request) { 
        //完成处理逻辑 
        return null; 
    }
    //设置自己的处理级别 
    protected Level getHandlerLevel() { 
        //设置自己的处理级别 
        return null; 
    } 
}

在处理者中涉及三个类:

  • Level类负责定义请求的处理级别;
  • Request类负责封装请求;
  • Response负责封装链中返回的结果。

这三个类都需要根据业务产生。

有关框架代码:

public class Level { 
    //定义一个请求和处理等级 
}
    
public class Request { 
    //请求的等级 
    public Level getRequestLevel(){ 
        return null; 
    } 
}

public class Response { 
    //处理者返回的数据 
}

在场景类或高层模块中对链进行组装,并传递请求,返回结果。

public class Client { 
    public static void main(String[] args) { 
        //声明所有的处理节点 
        Handler handler1 = new ConcreteHandler1(); 
        Handler handler2 = new ConcreteHandler2(); 
        Handler handler3 = new ConcreteHandler3(); 
        //设置链中的阶段顺序1-->2-->3 
        handler1.setNext(handler2); 
        handler2.setNext(handler3); 
        //提交请求,返回结果 
        Response response = handler1.handlerMessage(new Request()); 
    } 
}

在实际应用中,一般会有一个封装类对责任模式进行封装,也就是替代Client类,直接返回链中的第一个处理者,具体链的设置不需要高层次模块关系。这样,更简化了高层次模 块的调用,减少模块间的耦合,提高系统的灵活性。


责任链模式的优点

将请求和处理分开。

责任链模式的缺点

  • 性能问题。每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。
  • 调试不方便。特别是链条较长环节较多时,由于采用类似递归的方式,调试时逻辑可能比较复杂

注意事项

链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免 无意识地破坏系统性能。


责任链模式实例

这里采用古代女子“三从四德”中的“三从”作为实例,即“未嫁从父、既嫁从夫、夫死从子”。假设某一妇女想出门逛街,则需要多番请示。作为父亲、丈夫或儿子,只有两种选择:要不承担起责任来,允许她或不允许她逛街;要不就让她请示下一个人,这是整个社会体系的约束,应用到我们项目中就是业务规则。

我们可以设计这样一个顺序处理图:

同时得到这样一张类图:

类图中,三个实现类Father、Husband、Son只要实现构造函数和父类中的抽象方法response,具体由谁处理女性提出的请求,都转移到Handler抽象类中。

(1)IWomen接口及其实现Women类:定义并实现两个方法,分别是妇女个人状况和个人请求。

public interface IWomen {
	//获得个人状况
	public int getType();
	//获得个人请示,要出去逛街还是约会?
	public String getRequest();
}
import com.sfq.impl.IWomen;
public class Women implements IWomen {
	/*
	 * 通过int描述妇女个人状况
	 * 1--未出嫁
	 * 2--出嫁
	 * 3--夫死
	 */
	private int type = 0;
	private String request = "";
	//构造函数传递请求
	public Women(int _type, String _request) {
		this.type = _type;
		switch (this.type) {
		case 1: this.request = "女儿的请求是:" + _request; break;
		case 2: this.request = "妻子的请求是:" + _request; break;
		case 3: this.request = "母亲的请求是:" + _request; break;
		}
	}
	//获得个人状况
	@Override
	public int getType() {
		return this.type;
	}	
	//获得个人请示
	@Override
	public String getRequest() {
		return this.request;
	}
}

(2)Handler接口及其实现类Father、Husband、Son

public abstract class Handler {
	public final static int FATHER_LEVEL_REQUEST = 1;
	public final static int HUSBAND_LEVEL_REQUEST = 2;
	public final static int SON_LEVEL_REQUEST = 3;
	//能处理的级别
	private int level = 0;
	//责任传递,下一个责任人
	private Handler nextHandler;
	//每个类都说明一下自己能处理哪些请求
	public Handler(int _level) {
		this.level = _level;
	}
	//一个女性要求逛街,你要处理这个请求
	public final void HandleMessage(IWomen women) {
		if (women.getType() == this.level) {
			this.response(women);
		} else {
			if (this.nextHandler != null) {
				this.nextHandler.HandleMessage(women);
			} else {
				System.out.println("-----没地方请示了,按不同意处理-----\n");
			}
		}
	}
	/*如果不属于你处理的请求,应该让她找下一个环节的人。
	 *如女儿出嫁了,还向父亲请示,父亲告诉他,应该找丈夫请示。
	 */
	public void setNext(Handler _handler) {
		this.nextHandler = _handler;
	}
	//对请示的回应
	protected abstract void response(IWomen women);
}

在这里也用到模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应,如果已经达到环节结尾,则直接做不同意处理。

import com.sfq.impl.Handler;
import com.sfq.impl.IWomen;
public class Father extends Handler {
	public Father() {
		super(Handler.FATHER_LEVEL_REQUEST);
	}
	@Override
	protected void response(IWomen women) {
		System.out.println("-----女儿向父亲请示-----");
		System.out.println(women.getRequest());
		System.out.println("父亲的回答是:同意\n");
	}
}
import com.sfq.impl.Handler;
import com.sfq.impl.IWomen;
public class Husband extends Handler {
	public Husband() {
		super(Handler.HUSBAND_LEVEL_REQUEST);		
	}
	@Override
	protected void response(IWomen women) {
		System.out.println("-----妻子向丈夫请示-----");
		System.out.println(women.getRequest());
		System.out.println("丈夫的回答是:同意\n");
	}
}
import com.sfq.impl.Handler;
import com.sfq.impl.IWomen;
public class Son extends Handler {
	public Son() {
		super(Handler.SON_LEVEL_REQUEST);		
	}
	@Override
	protected void response(IWomen women) {
		System.out.println("-----母亲向儿子请示-----");
		System.out.println(women.getRequest());
		System.out.println("儿子的回答是:同意\n");
	}
}

(3)场景类实现

import java.util.ArrayList;
import java.util.Random;
import com.sfq.action.Father;
import com.sfq.action.Husband;
import com.sfq.action.Son;
import com.sfq.action.Women;
import com.sfq.impl.Handler;
import com.sfq.impl.IWomen;
public class Client {
	public static void main(String[] args) {
		// 随机挑选2个女性
		Random random = new Random();
		ArrayList<IWomen> arrayList = new ArrayList();
		for (int i = 0; i < 2; i++) {
			arrayList.add(new Women(random.nextInt(4), "我要出去逛街"));
		}
		//定义三个请示对象
		Handler father = new Father();
		Handler husband = new Husband();
		Handler son = new Son();
		//设置请示顺序
		father.setNext(husband);
		husband.setNext(son);
		for(IWomen women:arrayList) {
			father.HandleMessage(women);
		}
	}
}

结果
-----母亲向儿子请示-----
母亲的请求是:我要出去逛街
儿子的回答是:同意

-----女儿向父亲请示-----
女儿的请求是:我要出去逛街
父亲的回答是:同意

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥羊汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值