Android设计模式-责任链模式
来源:互联网 发布:凤岗淘宝摄影 编辑:程序博客网 时间:2024/06/05 08:20
介绍
责任链模式(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); }}
责任链模式的简单实现
以一个报账的情况为例,员工小李到公司财务报账5万元,首先请求组长签字,但他没有权限,于是组长找到了部门主管,他仍没有权限,主管找到经理,还是不行,最后经理找到了老板,老板审批通过。这个示例的过程就是一个责任链模式的简单应用,事实上,小李只与组长产生关联,后面具体由谁处理,小李并不关心,他只关心报账的结果,下面通过代码模拟一下:
public abstract class Leader { // 上一级领导 protected Leader nextHandler; //处理报账请求 // @param money 能批复的保障额度 public final void handleRequest(int money) { //自己可以处理该保障额度以下的报账请求 if(money <= limit()) { handle(money); } else { //自己无权限处理 if(null != nextHandler) { //交给上一级 nextHandler.handleRequest(money); } } } //自身能批复的额度权限 //@return 额度 /public abstract int limit(); //处理报账行为 // @param money 具体金额 public abstract void handle(int money);}
下面是具体领导者
//组长public class GroupLeader extends Leader { @Override public int limit() { return 1000; } @Override public void handle(int money) { System.out.println("组长批复报销" + money + "元"); }}//主管public class Direactor extends Leader { @Override public int limit() { return 5000; } @Override public void handle(int money) { System.out.println("主管批复报销" + money + "元"); }}//经理public class Manager extends Leader { @Override public int limit() { return 10000; } @Override public void handle(int money) { System.out.println("经理批复报销" + money + "元"); }}//Bosspublic class Bossextends Leader { @Override public int limit() { return Integer.MAX_VALUE; } @Override public void handle(int money) { System.out.println("老板批复报销" + money + "元"); }}
//Client客户端 小李向组长申请报账public class XiaoLi { public static void main(String[] args) { //创建各个领导类 GroupLeader groupLeader = new GroupLeader(); Director director = new Director(); Manager manager = new Manager(); Boss boss = new Boss(); //设置上一级领导处理者对象 groupLeader.nextHandler = director; director.nextHandler = manager; manager.nextHandler = boss; //发起请求 groupLeader.handleRequest(50000); }}
当组长不在时,也可以越过他直接找主管报账。事实上,这也是责任链模式的灵活之处,也就是说,请求的发起者可以从责任链的任意一个节点处发起请求。
对于责任链中任意一个节点的对象,其行为只有两个,一是处理请求,二是将请求移交给下一个节点的处理者。不允许将某个请求有还给上一个阶段对象。也就是说,责任链处理请求的结果只有两种,一种是某个节点处理完成,一种是所有节点均处理失败,前者称为纯的责任链,后者称为不纯的,实际应用中,大部分是不纯的责任链。
责任链模式实战
在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 android:name="com.test.action.ORDER_BROADCAST"/> </intent-filter></receiver><receiver android:name=".broadcast.order.SecondReceiver"> <intent-filter android:priority="100"> <action android:name="com.test.action.ORDER_BROADCAST"/> </intent-filter></receiver><receiver android:name=".broadcast.order.ThirdReceiver"> <intent-filter android:priority="10"> <action android:name="com.test.action.ORDER_BROADCAST"/> </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设计模式-责任链模式
- Android设计模式之责任链模式
- Android设计模式应用-责任链模式
- Android设计模式之责任链模式
- Android 设计模式 笔记 - 责任链模式
- Android设计模式~~~责任链模式
- Android设计模式-责任链模式
- Android设计模式实战---责任链模式
- Android的设计模式-责任链模式
- 责任链设计模式
- 责任链设计模式
- 设计模式---责任链
- 责任链设计模式
- 设计模式----责任链
- 设计模式-责任链
- 责任链设计模式
- 责任链设计模式
- 设计模式:责任链
- GD32F130FXP6学习笔记四:ARM 汇编指令集初识
- Java笔记
- HDU5127 Dogs' Candies(瞎暴力)
- Linux USB札记
- java-final关键字
- Android设计模式-责任链模式
- 高性能高可用的分布式唯一ID服务——mooon-uniq-id
- Vim E568:: duplicate cscope database not added 解决方法
- Sqlite教程
- 读程序 UVA1587 UVALive3214 POJ2160 Box
- 关于json解析的几种方法
- Vijos 1736题:铺地毯
- bzoj 2304: [Apio2011]寻路 (最短路+建图)
- 重视理论