设计模式——责任链模式

来源:互联网 发布:阿里云ecs上传文件 编辑:程序博客网 时间:2024/06/05 14:41

介绍

责任链模式(Iterator Pattern),是行为型设计模式之一。 我们将多个首尾相连所构成的模型称为链。对于链式结构,每个节点都可以被拆开再连接,因此具有很好的灵活性。将这样一种结构应用于编程领域,将每个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首端出发,沿着链的路径依次传递给每一个对象,直至有对象处理这个请求为止,这样的模式称为责任链模式。在上代码之前。先看看它的标准定义。

定义

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

使用场景

多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。

在请求处理者不明确的情况下长多个对象中的一个提交一个请求。

需要动态指定一组对象处理请求。

责任链模式的通用模板

public abstract class Handler {    //下一节点的处理者    protected Handler successor;    //请求处理    // @param condition    public abstract void handleRequest(String condition);}
//具体处理者1public class ConcreateHandler1 extends Handler {    @Override    public void handleRequest(String condition) {        //如果满足条件,请求将由责任链上的ConcreateHandler1节点处理        if(condition.equals("ConcreateHandler1")) {            System.out.println("ConcreateHandler1 handled");            return;        } else {            successor.handleRequest(condition);        }    }}
//具体处理者2public class ConcreateHandler2 extends Handler {    @Override    public void handleRequest(String condition) {        //如果满足条件,请求将由责任链上的ConcreateHandler2节点处理        if(condition.equals("ConcreateHandler2")) {            System.out.println("ConcreateHandler2 handled");            return;        } else {            successor.handleRequest(condition);        }    }}
//客户端public class Client {    public static void main(String[] args) {        //构造一个ConcreateHandler1对象        ConcreateHandler1 handler1 = new ConcreateHandler1();        //构造一个ConcreateHandler2对象        ConcreateHandler1 handler2 = new ConcreateHandler2();        //设置handler1的下一个节点        handler1.successor = handler2;        //设置handler2的下一个节点        handler2.successor = handler1;        //处理请求        handler1.handleRequest("ConcreateHandler2");    }}

角色介绍

Handler:抽象处理者,声明一个请求处理方法,并在其中保持一个对下一个处理节点Handler对象的引用。

ConcreteHandler:具体处理者角色,对请求进行处理,若不能处理则将该请求转发给下一个节点上的处理对象。

上面的责任链模式只是一个模板代码,因为对于请求来说,其形式是固定的,就是一个字符串,而判断一个节点上的对象是否能够处理该标志,则是字符串是否匹配。然而在大多数情况下,责任链中的请求和对应的处理规则不尽相同,在这种情况下可以将请求进行封装,同时对请求的处理规则也进行封装作为一个独立的对象。

首先仍然是AbstractHandler抽象处理者,它声明了处理者对象处理请求的方法和获取处理级别的方法,并对具体的处理转发逻辑进行了实现:

//抽象处理者public abstract class AbstractHandler {    //下一个节点上的处理者对象    protected AbstractHandler nextHandler;    //处理请求    // @param request 请求对象    public final void handleRequest(AbstractRequest request) {        //判断当前处理者对爱你过的处理级别是否匹配请求者的处理级别        if(getHandlerLevel() == request.getRequestLevel()) {            //匹配 则由该Handler对象处理            handle(request);        } else {            //不匹配 则将该请求对象转发给下一个节点上的请求对象            if(nextHandler != null) {                nextHandler.handleRequest(request);            } else {                //当所有处理者均不能处理该请求时输出                System.out.prinln("所有处理者均不能处理该请求");            }        }    }    //获取处理者对象的处理级别    // @return 处理级别    protected abstract int getHandlerLevel();    //每个处理者对象的具体处理方式    // @param request    protected abstract void handle(AbstractRequest);}

这种情况下责任转发逻辑由抽象处理类控制,而对于抽象请求者,其内部页声明了一个获取请求级别的方法,其与抽象处理者中返回的处理级别保持对应,什么级别的处理逻辑就对应什么样的请求级别。

//抽象请求者public abstract class AbstractRequest {    //处理对象    private Object obj;    public AbstractRequest(Object obj) {        this.obj = obj;    }    //获取处理内容对象    // @return 具体的内容对象    public Object getContent() {        return obj;    }    //获取请求级别    // @return 请求级别    public abstract int getRequestLevel();}

下面是三个请求则和三个处理者:

public class Request1 extends AbstractRequest {    public Request1(Object object) {        super(object);    }    @Override    public int getRequestLevel() {        return 1;    }}
public class Request2 extends AbstractRequest {    public Request2(Object object) {        super(object);    }    @Override    public int getRequestLevel() {        return 2;    }}
public class Request3 extends AbstractRequest {    public Request3(Object object) {        super(object);    }    @Override    public int getRequestLevel() {        return 3;    }}

处理者:

public class Handler1 extends AbstractHandler {    @Override    protected int getHandlerLevel() {        return 1;    }    @Override    protected void handle(AbstractRequest request) {        System.out.println("Handle1 handle request:" + request.getRequestLevel());    }}
public class Handler2 extends AbstractHandler {    @Override    protected int getHandlerLevel() {        return 2;    }    @Override    protected void handle(AbstractRequest request) {        System.out.println("Handle2 handle request:" + request.getRequestLevel());    }}
public class Handler3 extends AbstractHandler {    @Override    protected int getHandlerLevel() {        return 3;    }    @Override    protected void handle(AbstractRequest request) {        System.out.println("Handle3 handle request:" + request.getRequestLevel());    }}

Client客户端:

public class Client {    public static void main(String[] args) {        //构造三个处理对象        AbstractHandler handler1 = new Handler1();        AbstractHandler handler2 = new Handler2();        AbstractHandler handler3 = new Handler3();        //设置当前处理者对象的下一个节点 形成链条 注意 第三个处理者没有下一个节点        handler1.nextHandler = handler2;        handler2.nextHandler = handler3;        //构造三个请求者对象        AbstractRequest request1 = new Request("Request1");        AbstractRequest request2 = new Request("Request2");        AbstractRequest request3 = new Request("Request3");        //总是从链式的首端发起请求        handler1.handleRequest(request1);        handler1.handleRequest(request2);        handler1.handleRequest(request3);    }}

责任链模式实战

在Android中,可以借鉴责任链模式的思想来优化BroadcastReceiver使之成为一个全局的责任链处理者。在BroadcastReceiver的分类中,有序广播是根据优先级依次传播的,指导有接受者将其终止或者所有接受者都不终止它,这与责任链模式很相近。通过它可以轻松实现一种全局的责任链事件处理,这里我们创建了3个BroadcastReceiver:

public class FirstReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        int limit = intent.getIntExtra("limit", -1001);        //如果限制值为1000,则处理,否则交给下一个receiver处理        if(limit == 1000) {            String msg = intent.getStringExtra("msg");            Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();            abortBroadcast();        } else {            //添加信息发送给下一个Receiver            Bundle b = new Bundle();            b.putString("new","Message From FisrtReceiver");            setResultExtras(b);        }    }}

一个接受者能否处理本次广播的唯一条件是看广播中附加权限值是否与自身相等,只有满足limit == 1000 这个条件,才会处理广播并终止广播的继续传递,否则将在广播的intent中在附加一条信息并传播给下一个接收者:

public class SecondReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        int limit = intent.getIntExtra("limit", -1001);        //如果限制值为100,则处理,否则交给下一个receiver处理        if(limit == 100) {            String msg = intent.getStringExtra("msg");            Bundle b = getResultExtra(true);            String str = b.getString("new");            Toast.makeText(context,msg + "-----",Toast.LENGTH_SHORT).show();            abortBroadcast();        } else {            //添加信息发送给下一个Receiver            Bundle b = new Bundle();            b.putString("new","Message From SecondReceiver");            setResultExtras(b);        }    }}
//第三个Receiverpublic class ThirdReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        int limit = intent.getIntExtra("limit", -1001);        //如果限制值为10,则处理,否则交给下一个receiver处理        if(limit == 10) {            String msg = intent.getStringExtra("msg");            Bundle b = getResultExtra(true);            String str = b.getString("new");            Toast.makeText(context,msg + "-----",Toast.LENGTH_SHORT).show();            abortBroadcast();        } else {            //添加信息发送给下一个Receiver            Bundle b = new Bundle();            b.putString("new","Message From SecondReceiver");            setResultExtras(b);        }    }}

还需要在AndroidManifest中声明这三个Receiver:

<receiver android:name=".broadcast.order.FirstReceiver">    <intent-filter android:priority="1000">    </action></intent-filter></receiver><receiver android:name=".broadcast.order.SecondReceiver">    <intent-filter android:priority="100">    </action></intent-filter></receiver><receiver android:name=".broadcast.order.ThirdReceiver">    <intent-filter android:priority="10">    </action></intent-filter></receiver>

在Activity中发送一个广播:

public class OrderActivity extends Activity {    @Override    protected void onCreate(Bundle saveInstanceState) {        super.onCreate(saveInstanceState);        setContentView(R.layout.activity_main);        Button button = findViewById(R.id.order_send_btn);        button.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                Intent i = new Intent();                i.setAction("com.test.action.ORDER_BROADCAST");                i.putExtra("limit",100);                i.putExtra("msg","Message from OrderActivity");                sendOrderdBroadcast(i,null);            }        });    }}

上例中只有SecondReceiver能处理该广播。

总结

责任链模式的优点显而易见,就是可以对请求者和处理者解耦,提高代码的灵活性。

缺点是对链中请求处理者的遍历,如果处理者太多那么遍历必定会影响性能,特别是在一些递归调用中,要慎重。

参考资料

《Android源码设计模式解析与实战》

原创粉丝点击