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