设计模式学习笔记之六:责任链模式
我们公司使用的Enovia PLM系统是基于SOA架构的,PLM不仅仅是SAP的主数据源头,同时还需要跟其他的系统(例如供应商的DAM系统及公司的AS400系统)保持交互,系统跟系统的数据交互通过Web Service基于SOAP来实现,具体来说,PLM需要跟如下系统保持交互:
子系统 | 地区/功能 |
AFS1 | 中国,意大利 |
AFS2 | 北美 |
AS400 | 遗留系统 |
DAM | 供应商 |
ISR | 零售 |
PLM发送物料主数据到SAP是通过XML文件这种载体的,SAP有个PF(PI)系统专门读取PLM生成在固定共享文件夹的文件来接受数据,PI需要使用XSLT文件来作为转换文件,把PLM生成的XML转换成SAP能够读懂的格式,这里就引出了我们的主角,XSLT的transformaion文件,要知道每个ERP(AFS1,AFS2,AS400,DAM,ISR)的transformation文件内容都不一样,而且一个物料可以发送到不同的系统,只要这个物料的内容符合一定的要求,现在意大利的用户有一个需求,就是当我发送一个物料的时候,PLM系统应该能够基于每个ERP系统的规则对这个物料进行检验,如果合乎规则就应该把这个物料发送到相应系统,否则,不允许发送到相应系统。也就是说,物料1可能可以发送到AFS1,AFS2和AS400,物料2有可能只能发送到AFS1,而这一切都应该在java代码里面进行验证。
基于以上需求,我觉得责任链设计模式可以解决以上问题。
责任链模式的定义是这样的:
责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
基于对公司数据的保护,在这里我就不把项目中的代码贴出来了,我自己写了一个简单的责任链模式来阐述它的结构,跟我在公司写代码的习惯一样,我先画个UML类图:
抽象基类Chain
package com.singland.dp.chainofresponsibility; public abstract class Chain { private Chain nextNode; protected Chain getNextNode() { return nextNode; } protected void setNextNode(Chain nextNode) { this.nextNode = nextNode; } public abstract void handleRequest(int num); }
4个节点类
package com.singland.dp.chainofresponsibility; public class ChainNode1 extends Chain { @Override public void handleRequest(int num) { if (num < 10) { System.out.println("ChinaNode1 take in charge the number less than 10"); } else { Chain nextNode = getNextNode(); if (nextNode != null) { nextNode.handleRequest(num); } } } }
package com.singland.dp.chainofresponsibility; public class ChainNode2 extends Chain { @Override public void handleRequest(int num) { if (num >=10 && num < 20) { System.out.println("ChinaNode2 take in charge the number less than 20"); } else { Chain nextNode = getNextNode(); if (nextNode != null) { nextNode.handleRequest(num); } } } }
package com.singland.dp.chainofresponsibility; public class ChainNode3 extends Chain { @Override public void handleRequest(int num) { if (num >= 20 && num < 30) { System.out.println("ChinaNode3 take in charge the number less than 30"); } else { Chain nextNode = getNextNode(); if (nextNode != null) { nextNode.handleRequest(num); } } } }
package com.singland.dp.chainofresponsibility; public class ChainLastNode extends Chain { @Override public void handleRequest(int num) { System.out.println("Why I'm here, it seems the number is greater than 30 !"); } }
测试类
package com.singland.dp.chainofresponsibility; import org.junit.Test; public class MyTest { @Test public void test() { //assemble chain of responsibility Chain node1 = new ChainNode1(); Chain node2 = new ChainNode2(); Chain node3 = new ChainNode3(); Chain lastNode = new ChainLastNode(); node1.setNextNode(node2); node2.setNextNode(node3); node3.setNextNode(lastNode); //use chain of responsibility node1.handleRequest(200); } }
在测试类里面,当责任链组装好了之后,流程图看起来就是这个样子的:
这样,不管你在测试类里面输入什么样的数字,责任链条里面都一定会有一个节点根据你的数字大小来处理,而客户端本身并不知道具体是哪个节点处理了这个请求,客户端只需要知道请求一定会被某个节点处理。
责任链模式的好处是:将业务逻辑代码依据条件分离开,单个业务逻辑块的修改不影响其他业务逻辑块,对于节点的修改不会造成客户端的调用代码的改变,实现了松耦合;可以动态地组织和分配责任。