用責任鏈模式實現(xiàn) OA 系統(tǒng)中的漲薪流程審批
本文轉(zhuǎn)載自微信公眾號「Java極客技術(shù)」,作者鴨血粉絲。轉(zhuǎn)載本文請聯(lián)系Java極客技術(shù)公眾號。
Hello 大家好,我是阿粉,工作中我們經(jīng)常會遇到很多需要上級或者上級的上級一層層審批的流程,作為程序員如果要讓你實現(xiàn)這個流程,你會采用什么方式呢?
好了思考一分鐘結(jié)束,很顯然大家一致的回答就是責任鏈模式。那么什么是責任鏈模式呢?如何使用責任鏈模式去完成這個流程呢?下面我們來看一下。
需求分析
開發(fā)之前的第一步是需求分析,我們這個場景是這樣的,阿粉準備跟領(lǐng)導 A 申請一下漲薪,最滿意的結(jié)果當時是直接跟上級領(lǐng)導 A 申請就直接過了,但是理想很豐滿,現(xiàn)實很骨干。領(lǐng)導 A 也只是一個小組長并沒有直接漲薪的權(quán)利,所以領(lǐng)導也要向他的上級 B 進行申請,而然到這里并沒有結(jié)束,因為 B 還要跟人資管事的 C 進行申請,人事 C 同事最終還要跟 CEO 進行申請。
想想這個流程有多么的負責,不禁的阿粉就不抱希望了,畢竟阿粉只是一個小開發(fā),想漲個工資怎么這么難,阿粉哭暈在廁所。
在這個場景里面有這個幾個需求點,就是每個人都有自己的權(quán)限,在自己能力范圍之內(nèi)的事情可以直接審批,但是不在自己能力的范圍里面只能向上反饋;申請的內(nèi)容是加薪,最終 CEO 具有最終決策權(quán)。
初始版本
首先我們定義一個工單的 model,具體代碼如下
- package com.test.model.chain;
- public class ApplyModel {
- //申請人名稱
- private String applyName;
- //工單類型
- private String type;
- //工單內(nèi)容
- private String content;
- //漲薪幅度
- private int salary;
- //...get set 省略
- }
初始版本的申請漲薪代碼如下,根據(jù)不同的領(lǐng)導和不同的申請類型來進行相應的邏輯處理。
- package com.test.model.chain;
- public class ClientApplyServiceDemo {
- public void handlerApply(String leader, ApplyModel applyModel) {
- if ("A".equals(leader)) {
- if ("漲薪".equals(applyModel.getType()) && applyModel.getSalary() < 100) {
- System.out.println("小于 100 的漲薪,A 可以直接處理");
- } else {
- System.out.println("大于 100 的漲薪,A 不能處理");
- }
- }
- if ("B".equals(leader)) {
- if ("漲薪".equals(applyModel.getType()) && applyModel.getSalary() < 300) {
- System.out.println("小于 300 的漲薪,B 可以直接處理");
- } else {
- System.out.println("大于 300 的漲薪,B 不能處理");
- }
- }
- if ("C".equals(leader)) {
- if ("漲薪".equals(applyModel.getType()) && applyModel.getSalary() < 500) {
- System.out.println("小于 500 的漲薪,C 可以直接處理");
- } else {
- System.out.println("大于 500 的漲薪,C 不能處理");
- }
- }
- if ("CEO".equals(leader)) {
- if ("漲薪".equals(applyModel.getType()) && applyModel.getSalary() < 800) {
- System.out.println("小于 800 的漲薪,CEO 可以直接處理");
- } else {
- System.out.println("大于 800 的漲薪,CEO 不能處理,下次吧,別做夢了");
- }
- }
- }
- }
上面的代碼請勿服用,否則被開除阿粉不背鍋。
很顯然上面的代碼用一個字來形容,那就是爛!兩個字就是真爛!!實際工作中要是寫出這樣的代碼,那么恭喜你,你已經(jīng)走在被炒魷魚的路上了。
那么我們?nèi)绾瓮ㄟ^責任鏈的設(shè)計模式讓整個代碼優(yōu)雅起來呢?
什么是責任鏈模式
使多個對象都有處理請求的機會,從而避免請求的發(fā)起者和接收者之間的耦合,將這個對象連成一條鏈,并沿著這條鏈傳遞請求,直到有一個對象處理它為止。
重構(gòu)
思考一樣,我們有上下級,而且每個領(lǐng)導都有上級以及自己能處理的能力范圍,所以我們可以按照下面的類圖進行設(shè)計,我們可以將申請工單的請求按照職級向上傳遞,當自己處理不了的時候就反饋給上級,上級完成不了的時候就會傳遞給他的上級,直到某個級別能處理為止。
首先我們設(shè)計一個抽象類 Leader,代碼如下
- package com.test.model.chain.leader;
- import com.test.model.chain.ApplyModel;
- public abstract class Leader {
- protected Leader leader;
- public void setLeader(Leader leader) {
- this.leader = leader;
- }
- public abstract void handlerApply(ApplyModel applyModel);
- }
下面是具體四個子類,具體的代碼如下
- package com.test.model.chain.leader.impl;
- import com.test.model.chain.ApplyModel;
- import com.test.model.chain.leader.Leader;
- public class ALeader extends Leader {
- protected Leader leader;
- @Override
- public void setLeader(Leader leader) {
- this.leader = leader;
- }
- @Override
- public void handlerApply(ApplyModel applyModel) {
- if (applyModel.getSalary() < 100) {
- System.out.println("申請金額為" + applyModel.getSalary() + "小于 100,A 可以處理");
- } else {
- leader.handlerApply(applyModel);
- }
- }
- }
- package com.test.model.chain.leader.impl;
- import com.test.model.chain.ApplyModel;
- import com.test.model.chain.leader.Leader;
- public class BLeader extends Leader {
- protected Leader leader;
- @Override
- public void setLeader(Leader leader) {
- this.leader = leader;
- }
- @Override
- public void handlerApply(ApplyModel applyModel) {
- if (applyModel.getSalary() < 300) {
- System.out.println("申請金額為" + applyModel.getSalary() + "小于 300,B 可以處理");
- } else {
- leader.handlerApply(applyModel);
- }
- }
- }
- package com.test.model.chain.leader.impl;
- import com.test.model.chain.ApplyModel;
- import com.test.model.chain.leader.Leader;
- public class CLeader extends Leader {
- protected Leader leader;
- @Override
- public void setLeader(Leader leader) {
- this.leader = leader;
- }
- @Override
- public void handlerApply(ApplyModel applyModel) {
- if (applyModel.getSalary() < 500) {
- System.out.println("申請金額為" + applyModel.getSalary() + "小于 500,C 可以處理");
- } else {
- leader.handlerApply(applyModel);
- }
- }
- }
- package test.model.chain.leader.impl;
- import test.model.chain.ApplyModel;
- import com.test.model.chain.leader.Leader;
- public class CEOLeader extends Leader {
- protected Leader leader;
- @Override
- public void setLeader(Leader leader) {
- this.leader = leader;
- }
- @Override
- public void handlerApply(ApplyModel applyModel) {
- if (applyModel.getSalary() < 1000) {
- System.out.println("申請金額為" + applyModel.getSalary() + "小于 1000,CEO 同意了");
- } else {
- System.out.println("想漲薪" + applyModel.getSalary() + "這么多,下次吧");
- }
- }
- }
抽象類中有一個屬性,一個構(gòu)造方法和一個抽象方法;相應的子類分別實現(xiàn)了各自的抽象方法,用來處理各自的能力范圍之內(nèi)的事情。每個實現(xiàn)類根據(jù)自身的能力覺得如果處理相應的申請條件,這樣的結(jié)構(gòu)可以更加可讀,并且每個人的處理能力互不影響,如果誰的能力有變化只要修改自己的那一部分就可以了。接下來我們看下客戶端是如果調(diào)用的。
- package com.test.model.chain;
- import com.test.model.chain.leader.Leader;
- import com.test.model.chain.leader.impl.ALeader;
- import com.test.model.chain.leader.impl.BLeader;
- import com.test.model.chain.leader.impl.CEOLeader;
- import com.test.model.chain.leader.impl.CLeader;
- public class ClientApplyService {
- public static void main(String[] args) {
- ApplyModel applyModel = new ApplyModel();
- applyModel.setApplyName("阿粉");
- applyModel.setContent("申請漲薪");
- applyModel.setSalary(50);
- Leader aLeader = new ALeader();
- Leader bLeader = new BLeader();
- Leader cLeader = new CLeader();
- Leader ceoLeader = new CEOLeader();
- aLeader.setLeader(bLeader);
- bLeader.setLeader(cLeader);
- cLeader.setLeader(ceoLeader);
- aLeader.handlerApply(applyModel);
- }
- }
我們分別修改漲薪的幅度數(shù)值,看下執(zhí)行的結(jié)果。
申請 50 漲幅的運行結(jié)果如下(忽略具體的數(shù)值,相信我如果漲工資只漲 50 ,那簡直就是侮辱,這種公司還是盡早躲開吧)。
將漲薪幅度調(diào)整為 150,運行結(jié)果如下。
將漲幅調(diào)整為 550,運行結(jié)果如下:
將漲幅調(diào)整為 1550,運行結(jié)果如下:
經(jīng)過我們的重構(gòu),整個代碼結(jié)構(gòu)已經(jīng)非常的清晰了,現(xiàn)在的代碼已經(jīng)比初始版本優(yōu)雅很多了,使用責任鏈的好處就是將請求一層層的處理,直到有能處理的對象為止,可以避免耦合。