23.1 场景问题
23.1.1 申请聚餐费用
来考虑这样一个功能:申请聚餐费用的管理。
很多公司都有这样的福利,就是项目组或者是部门可以向公司申请一些聚餐费用,用于组织项目组成员或者是部门成员进行聚餐活动,以增进人员之间的情感,更有利于工作中的相互合作。
申请聚餐费用的大致流程一般是:由申请人先填写申请单,然后交给领导审查,如果申请批准下来了,领导会通知申请人审批通过,然后申请人去财务核领费用,如果没有核准,领导会通知申请人审批未通过,此事也就此作罢了。
不同级别的领导,对于审批的额度是不一样的,比如:项目经理只能审批500元以内的申请;部门经理能审批1000元以内的申请;而总经理可以审核任意额度的申请。
也就是说,当某人提出聚餐费用申请的请求后,该请求会由项目经理、部门经理、总经理之中的某一位领导来进行相应的处理,但是提出申请的人并不知道最终会由谁来处理他的请求,一般申请人是把自己的申请提交给项目经理,或许最后是由总经理来处理他的请求,但是申请人并不知道应该由总经理来处理他的申请请求。
那么该怎样实现这样的功能呢?
23.1.2 不用模式的解决方案
分析上面要实现的功能,主要就是要根据申请费用的多少,然后让不同的领导来进行处理就可以实现了。也就是有点逻辑判断而已,示例代码如下:
/** * 处理聚餐费用申请的对象 */ public class FeeRequest { /** * 提交聚餐费用申请给项目经理 * @param user 申请人 * @param fee 申请费用 * @return 成功或失败的具体通知 */ public String requestToProjectManager(String user,double fee){ String str = ""; if(fee < 500){ //项目经理的权限比较小,只能在500以内 str = this.projectHandle(user, fee); }else if(fee < 1000){ //部门经理的权限只能在1000以内 str = this.depManagerHandle(user, fee); }else if(fee >= 1000){ //总经理的权限很大,只要请求到了这里,他都可以处理 str = this.generalManagerHandle(user, fee); } return str; } /** * 项目经理审批费用申请,参数、返回值和上面是一样的,省略了 */ private String projectHandle(String user, double fee) { String str = ""; //为了测试,简单点,只同意小李的 if("小李".equals(user)){ str = "项目经理同意"+user+"聚餐费用"+fee+"元的请求"; }else{ //其它人一律不同意 str = "项目经理不同意"+user+"聚餐费用"+fee+"元的请求"; } return str; } /** * 部门经理审批费用申请,参数、返回值和上面是一样的,省略了 */ private String depManagerHandle(String user, double fee) { String str = ""; //为了测试,简单点,只同意小李申请的 if("小李".equals(user)){ str = "部门经理同意"+user+"聚餐费用"+fee+"元的请求"; }else{ //其它人一律不同意 str= "部门经理不同意"+user+"聚餐费用"+fee+"元的请求"; } return str; } /** * 总经理审批费用申请,参数、返回值和上面是一样的,省略了 */ private String generalManagerHandle(String user, double fee) { String str = "";
//为了测试,简单点,只同意小李的 if("小李".equals(user)){ str = "总经理同意"+user+"聚餐费用"+fee+"元的请求"; }else{ //其它人一律不同意 str = "总经理不同意"+user+"聚餐费用"+fee+"元的请求"; } return str; } } |
写个客户端来测试看看效果,示例代码如下:
public class Client { public static void main(String[] args) { FeeRequest request = new FeeRequest();
//开始测试 String ret1 = request.requestToProjectManager("小李", 300); System.out.println("the ret="+ret1); String ret2 = request.requestToProjectManager("小张", 300); System.out.println("the ret="+ret2);
String ret3 = request.requestToProjectManager("小李", 600); System.out.println("the ret="+ret3); String ret4 = request.requestToProjectManager("小张", 600); System.out.println("the ret="+ret4);
String ret5 = request.requestToProjectManager("小李", 1200); System.out.println("the ret="+ret5); String ret6 = request.requestToProjectManager("小张", 1200); System.out.println("the ret="+ret6); } } |
运行结果如下:
the ret1=项目经理同意小李聚餐费用300.0元的请求 the ret2=项目经理不同意小张聚餐费用300.0元的请求 the ret3=部门经理同意小李聚餐费用600.0元的请求 the ret4=部门经理不同意小张聚餐费用600.0元的请求 the ret5=总经理同意小李聚餐费用1200.0元的请求 the ret6=总经理不同意小张聚餐费用1200.0元的请求 |
23.1.3 有何问题
上面的实现很简单,基本上没有什么特别的难度。仔细想想,这么实现有没有问题呢?仔细分析申请聚餐费用的业务功能和目前的实现,主要面临着如下问题:
- 聚餐费用申请的处理流程是可能会变动的。
比如现在的处理流程是:提交申请给项目经理,看看是否适合由项目经理处理,如果不是à看看是否适合由部门经理处理,如果不是à总经理处理的步骤。今后可能会变化成:直接提交给部门经理,看看是否适合由部门经理处理,如果不是à总经理处理这样的步骤。也就是说,对于聚餐费用申请,要求处理的逻辑步骤是灵活的。 - 各个处理环节的业务处理也是会变动的。
因为处理流程可能发生变化,也会导致某些步骤的具体的业务功能发生变化,比如:原本部门经理审批聚餐费用的时候,只是判断是否批准;现在,部门经理可能在审批聚餐费用的时候,核算本部门的实时成本,这就出现新的业务处理功能了。
如果采用上面的实现,要是处理的逻辑发生了变化,解决的方法,一个是生成一个子类,覆盖requestToProjectManager方法,然后在里面实现新的处理;另外一个方法就是修改处理申请的方法的源代码来实现。要是具体处理环节的业务处理的功能发生了变化,那就只好找到相应的处理方法,进行源代码修改了。
总之都不是什么好方法,也就是说,如果出现聚餐费用申请的处理流程变化的情况,或者是出现各个处理环节的功能变化的时候,上面的实现方式是很难灵活的变化来适应新功能的要求的。
把上面的问题抽象一下:客户端发出一个请求,会有很多对象都可以来处理这个请求,而且不同对象的处理逻辑是不一样的。对于客户端而言,无所谓谁来处理,反正有对象处理就可以了。
而且在上述处理中,还希望处理流程是可以灵活变动的,而处理请求的对象需要能方便的修改或者是被替换掉,以适应新的业务功能的需要。
请问如何才能实现上述要求?