前情提要

上集讲到小光梳理了公司的组织架构, 利用组合模式建立起了一个可扩展变化的多层的组织架构体系. 更清晰地明确了公司各个层级, 各个部门的职责. 大家明确职责, 通力合作, 让"小光热干面"这个招牌越做越好.

然而, 小光毕竟是经历过几任大企业的人啊, 弄好组织结构只是小光企业管理的第一步, 接下来小光准备要梳理下工作流了.

所有示例源码已经上传到Github, 戳这里

比如采购的审批流程

刚开始, 小光只有光谷一个店的时候, 很多时候采购某些东西也就没有什么流程, 大家一商量, 小光拍板, 就派人去采购了. 然而, 现在发展到好几个分店了, 小光肯定不能做到事事过问了, 故而会有一些放权, 但是某些情况(大件的采购)小光肯定还是想要到自己这里审批的.

想到这些, 小光想着第一个需要建立的就是这个采购审批流程了.

做一个采购审批系统

先分析问题

那么该怎么做呢?
正所谓问对了问题, 也就解决了一半. 小光一贯的做法, 是先想清楚问题是什么, 然后再针对性的出解决方案.

那么, 再回头看看, 问题具体是什么呢?

  1. 一个采购申请的审批流程系统
  2. 不同物件采购的审批流程并不是一样的(有的可能会到小光那儿, 有的没有必要)
  3. 同一个审批流程也可能会有变化(如上期组织结构所言, 公司组织结构会不断调整, 肯定会影响到采购审批层级的变化).

相应的解决点

问清楚了问题, 小光针对性的想了下方案的特性:

  1. 首先肯定是一个流程化的东东, 也就是说类似流水线的处理审批单. 例如采购员提出采购单, 采购部经理审批盖章, 到总经理审批...

  2. 不只是一条这样的流水线, 不同类型审批单的流水线不一致, 故而应该是有几条流水线.

  3. 因为流水线上的操作员(由于公司层级的调整, 部门变化)会变化, 故而流水线的每个节点最好是可定制的.

解决之道

了解了问题及其对应的特性, 小光开始了自己的采购审批系统设计.

首先, 对于第一个特性, 小光心想, 这很简单, 实际上就是一个指向性的调用嘛, A调用B, B再调用C...如此这般即可.

当然, 小光面向对象的编程思想已经深入脑髓, 他将采购员, 采购经理, 总经理都对象化了. 另外, 采购经理和总经理以及小光, 都视为是可以处理采购申请的人, 故而抽象出了一个RequestHandler:

RequestHandler(采购申请处理人)

public abstract class RequestHandler {// 上一级的处理人员private RequestHandler mNext;public RequestHandler(RequestHandler next) {this.mNext = next;}/*** 处理采购需求* @param req*/public void handleRequest(Request req) {printHandling(req);if (mNext != null) {mNext.handleRequest(req);}}protected void printHandling(Request req) {System.out.println(this.toString() + "审批了:" + req);}@Overridepublic abstract String toString();
}复制代码

采购经理:

public class PurchasingManager extends RequestHandler {/*** 构造时, 传入下一个处理人* @param next 下一个处理人*/public PurchasingManager(RequestHandler next) {super(next);}@Overridepublic String toString() {return "采购部经理";}
}复制代码

总经理和小光的实现与采购经理类似, 在此略过, 大家可以参看github上的源码.

为了满足问题的第2点:

不同物件采购的审批流程并不是一样的(有的可能会到小光那儿, 有的没有必要)

还需要有一些定制的流程:

public class RequestFlow {public static final int TYPE_SMALL_REQUEST = 1;public static final int TYPE_NORMAL_REQUEST = 2;public static final int TYPE_BIG_REQUEST = 3;public static RequestHandler getRequestChain(int type) {switch (type) {// 小物件, 只需采购经理审批case TYPE_SMALL_REQUEST:return new PurchasingManager(null);// 一般物件, 需要总经理审批case TYPE_NORMAL_REQUEST:return new PurchasingManager(new GeneralManager(null));// 大件物品, 需要小光审批case TYPE_BIG_REQUEST:default:return  new PurchasingManager(new GeneralManager(new XiaoGuang(null)));}}
}复制代码

让我们看看采购员的请求方式:

// 采购员
public class Buyer {public static void main(String[] args) {// 小需求Request smallRequest = new Request("10箱饮料");RequestFlow.getRequestChain(RequestFlow.TYPE_SMALL_REQUEST).handleRequest(smallRequest);// 一般需求Request normalRequest = new Request("10套桌椅");RequestFlow.getRequestChain(RequestFlow.TYPE_NORMAL_REQUEST).handleRequest(normalRequest);// 大需求Request bigRequest = new Request("一套同步电子显示大屏");RequestFlow.getRequestChain(RequestFlow.TYPE_BIG_REQUEST).handleRequest(bigRequest);}
}复制代码

// 小需求 输出:
采购经理审批了:10箱饮料采购申请// 一般需求  输出:
采购经理审批了:10套桌椅采购申请
总经理审批了:10套桌椅采购申请// 大需求 输出:
采购经理审批了:一套同步电子显示大屏采购申请
总经理审批了:一套同步电子显示大屏采购申请
小光审批了:一套同步电子显示大屏采购申请复制代码

可以看到, 小光目前设计的这套系统是可以业务审批流程的需求的. 我们这里RequestFlow实际上采用简单工厂的模式, 适用于流程数比较少的情况. 如果考虑到后续的组织架构的变化影响什么的, 这块是值得重构一下的.


另外一个可优化的是, 我们实际上并不需要这么多的流水线, 可能只需要定制最长的那条, 然后在每个节点上根据传过来的审批请求来决定是否在当前节点就消化掉, 还是说还要传给上一级处理. 大家可以自己尝试修改下~~

故事之后

故事情节相对简单, 然而确确实实这个就是责任链模式的一个应用. 照例, 我们上UML类图, 看下各个部分的关系(为了清晰展示链的关系, 类图中国舍弃RequestFlow这个工厂):

责任链模式
很多对象由每一个对象对其下家的引用(mNext)而连接起来形成一条链. 请求在这个链上传递, 直到链上的某一个对象决定处理此请求.
行为解耦的一种模式, 调用者并不确切知道也无需知道行为的执行者是谁.

扩展阅读一

开发Android的同学可能都用过大名鼎鼎的OkHttp了, OkHttp的核心其实就是其拦截器链(interceptor chain)的实现. 个人认为其最巧妙的也是这个拦截器链的实现了, 完美契合.

让我们先简单缕下OkHttp的request流程:

简单分析CacheInterceptor(OkHttp的缓存实现):

  @Override public Response intercept(Chain chain) throws IOException {...// 取缓存的ResponseResponse cacheResponse = strategy.cacheResponse;// 如果缓存满足要求, 直接返回. 相当于采购经理能够审批该采购请求, 无需上报给总经理.if (networkRequest == null) {return cacheResponse.newBuilder().cacheResponse(stripBody(cacheResponse)).build();}// 如果不能, 则交给链路的下一个责任人来处理.try {networkResponse = chain.proceed(networkRequest);} finally {...}// 对一个链点返回的response做处理, 看是否要缓存起来.Response response = networkResponse.newBuilder().cacheResponse(stripBody(cacheResponse)).networkResponse(stripBody(networkResponse)).build();if (HttpHeaders.hasBody(response)) {CacheRequest cacheRequest = maybeCache(response, networkResponse.request(), cache);response = cacheWritingResponse(cacheRequest, response);}return response;}复制代码

大家可以看到, 只是一个典型的责任链模式的运用.
牛逼的是, OkHttp中的拦截器(interceptor)不仅仅是单向的一个链点, 而是一个双向的回路. 每个链路节点, 在request的过程中会做一次拦截处理, 诸如是否直接返回缓存, 加上统一的UserAgent等; 在response回来之后会再做一次拦截处理, 例如缓存, 根据response header做相关处理等. 如下:

okhttp

强烈建议Android开发的同学可以深入研究下OkHttp的interceptor链这块的处理, 肯定是受益匪浅~


搭建后初步的审批体系, 小光又开始畅想未来了~~


最近工作真的是太忙了, 本系列延期了又延期, 抱歉.


借自己的广告位, 广告一波
大量高级Android坑位求自荐, 求推荐.
关键词:
alibaba.com这个App的开发
坐标杭州
3年及以上Android平台开发经验
简历请发至anly_jun@163.com, 谢谢.


采购申请的处理流程 --- 责任链模式相关推荐

  1. 设计模式-请假流程-责任链模式

    责任链模式的定义 ​ 首先我们可以先看一下责任链模式的定义: ​ Avoid coupling the sender of a request to its receiver by giving mo ...

  2. 《JAVA设计模式系列》责任链模式

    文章目录 责任链模式 责任链模式优缺点 应用场景 责任链模式的结构 实现流程 责任链模式 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这 ...

  3. 简易理解设计模式之:责任链模式——OA中请假流程示例

    介绍: 责任链模式属于行为型设计模式.它的定义为:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,只到有对象处理它为止. 类图: ...

  4. 重写报销流程,责任链模式实现

    之前写了一个状态机模式报销流程,用的状态机,可能受了WF的影响,处理这类似的流程首先想到状态机,可是怎么看怎么别扭,终于想到了一个非常合适的模式--责任链模式 图以后再补上,先贴出代码,需求和以前一样 ...

  5. Java设计模式8,校验、审批流程改善神器,责任链模式

    目录 一.责任链模式 二.责任链模式的优缺点 1.优点 2.缺点 三.违背原则方案 1.Programmer实体类 2.数据校验 3.但是,似乎违反了一些设计原则 四.通过责任链模式重构代码 1.链路 ...

  6. java工作流 责任链模式 审核审批流程 方法二

    因为最近在搞一些工作流的事情,而传统的Activity等工作流又太重,不太适合我们的系统,所以在网上找到了Apache Commons Chain这个实现比较轻的Command模式与责任链模式结合的工 ...

  7. 【设计模式系列】行为型之责任链模式

    目录 背景 理论 实践 总结 背景 责任链模式,小编在自己项目迭代过程也参与了维护和设计实现:本篇博文主要针对该设计模型进行总结和实践: 简单举例日常生活或者工作中能够接触的责任链模式场景:采购审批流 ...

  8. 【设计模式】第五章 责任链模式

    第五章 责任链模式 文章目录 第五章 责任链模式 一.介绍 二.结构 三.实现 一.介绍 在现实生活中,一个事件需要经过多个对象处理是很常见的场景.例如,采购审批流程.请假流程等.公司员工请假,可批假 ...

  9. 设计模式 | 责任链模式及典型应用

    本文的主要内容: 介绍责任链模式 请假流程示例 责任链模式总结 源码分析Tomcat Filter中的责任链模式 责任链模式 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程 ...

最新文章

  1. 关于校验规则(Validation Rule)和业务规则(Bussiness Rule)的思考
  2. UVa10000_Longest Paths(最短路SPFA)
  3. 新物质?新材料?探索元素周期表,机器学习帮你找!
  4. [UVa1213]Sum of Different Primes(递推,01背包)
  5. Unity3D游戏制作 移动平台上的角色阴影制作
  6. LeetCode MySQL 608. 树节点
  7. PHP实现调用淘宝SDK开放接口返回天猫或淘宝商品详情
  8. ApacheCN Linux 译文集(二) 20211206 更新
  9. 上市即巅峰!走乐视老路的暴风 实控人冯鑫是下一个贾跃亭?
  10. toad软件 insert批量操作_AE创建、PR制作,动态字幕跨软件也能批量操作
  11. 压缩JS方法:uglifyjs
  12. 自学it18大数据笔记-第二阶段Hive-day4——会持续更新……
  13. shell 第三次练习
  14. 计算机二级文化基础知识,全国计算机二级office考试内容
  15. ❤️PPT素材网站推荐❤️让你的PPT更加迷人❤️
  16. 栈判断字符串是否为中心对称_数据结构 Stacks 栈
  17. 国际音标IPA、DJ音标和美国KK音标对照表
  18. vue 路由地址不跳转 解决办法
  19. 英伟达Q3财报解读:营收连续四季度下滑 下一个增长拐点何时来?
  20. D类音频功放(CS8120例)

热门文章

  1. 车辆检测--A Closer Look at Faster R-CNN for Vehicle Detection
  2. LeetCode 221. Maximal Square----动态规划--谷歌面试算法题--Python解法
  3. python 函数调用列表,函数调用列表的Python oneliner
  4. java反射 数组类,乐字节Java反射之三:方法、数组、类加载器和类的生命周期
  5. puppeteer php,puppeteer 页面爬取实例(元素遍历)
  6. linux如何给用户加sudo权限,如何在Linux环境为用户添加sudo权限
  7. dataset的去重计数 g2_去互联网公司面试,面试官问我SpringCloud,附答案
  8. Logstash(四)插件Output详解
  9. 用VSCode写python的正确姿势
  10. App混合应用Appium自动化测试框架技术难点