請假有點麻煩
大家好,我是小趙,現任藏劍山庄高級鑄劍師,山庄的鑄劍師團隊一共有十多個組,我就是其中的小組長之一,我有七個手下。
今天,小明來找我請假,說他家里出了點狀況,需要請一個月的假,可我只是小組長,這么長的假期我是沒權利做主的,我簽完字,就叫他去找部門經理,然后小明拿着請假條去找部門經理,部門經理簽字了,又讓小明去找總經理簽字,然后小明又拿着請假條去找總經理,最后總經理簽字,這個假才算請完。
后來才知道,3天以下的假小組長簽字即可,3-7天的假需要小組長和部門經理簽字,7以上的假小組長和部門經理簽完字后還需要總經理簽字。
這個流程在各個企業里面是非常常見的。
咱們就來研究一下這個請假的流程。
角色1:請假條,其實可以理解成請假人,因為請假條上自然有請假人信息。
角色2:領導人,小組長、部門經理、總經理都是審批人。
動作:領導人審批請假條。
那么類圖也就可以畫出來了:
現在我們把程序寫出來,看看請假是怎么請的:
請假條抽象:
public interface ILeave { String getName();//請假人姓名 int getNum();//請假天數 String getContent();//請假條內容 }
請假條:
public class Leave implements ILeave{ private String name;//姓名 private int num;//請假天數 private String content;//請假內容 public Leave(String name, int num, String content) { this.name = name; this.num = num; this.content = content; } public String getName() { return name; } public int getNum() { return num; } public String getContent() { return content; } }
處理者抽象:
public interface IHandler { void handleLeave(ILeave leave);//處理請假條 }
小組長:
public class GroupLeader implements IHandler { @Override public void handleLeave(ILeave leave) { System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("小組長審批:同意。"); } }
部門經理:
public class Manager implements IHandler { @Override public void handleLeave(ILeave leave) { System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("部門經理審批:同意。"); } }
總經理:
public class BigManager implements IHandler { @Override public void handleLeave(ILeave leave) { System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("總經理審批:同意。"); } }
客戶端:
public static void main(String[] args) { //請假條來一張 ILeave leave = new Leave("小花",5,"身體不適"); //小組長第一個審批 IHandler groupLeader = new GroupLeader(); groupLeader.handleLeave(leave); if(leave.getNum() >= 3){ IHandler manager = new Manager(); manager.handleLeave(leave); } if(leave.getNum() >= 7){ IHandler bigManager = new BigManager(); bigManager.handleLeave(leave); } }
輸出:
小花請假5天,身體不適。
小組長審批:同意。
小花請假5天,身體不適。
部門經理審批:同意。
這個程序寫出來是有問題的。
如果老板還要審批該怎么辦?在外面繼續加個if判斷?一個優秀的程序應該具有高內聚低耦合的特性,這個程序審批規則寫在外面是不合理的。
正確的邏輯應該是什么樣的呢? 應該是小花遞了請假條之后,就只需要等結果即可,而不是找了這個審批,回來后又跑去找那個審批。
請假制度的優化
對於請假制度的優化問題,我非常上心,如果我為公司設計了健全的制度,說不定升職加薪就是分分鍾的事情。
主要要解決的問題就是職責隔離,小花是申請者,領導是審批者,至於審批規則應該是領導去把控,所以每個領導需要知道自己的上級,也就是下一個審批人是誰。
由此可見,應該把interface改為abstract抽象類增加程序靈活度,使用模板方法模式將領導共同要遵守的規則收集到父類。
類圖畫出來也差不多,變化的只是處理者抽象:
請假條抽象:
public interface ILeave { String getName();//請假人姓名 int getNum();//請假天數 String getContent();//請假條內容 }
請假條:
public class Leave implements ILeave{ private String name;//姓名 private int num;//請假天數 private String content;//請假內容 public Leave(String name, int num, String content) { this.name = name; this.num = num; this.content = content; } public String getName() { return name; } public int getNum() { return num; } public String getContent() { return content; } }
處理者抽象:
public abstract class Handler { protected final static int NUM_ONE = 1; protected final static int NUM_THREE = 3; protected final static int NUM_SEVEN = 7; //該領導處理的請假天數區間 private int numStart = 0; private int numEnd = 0; //領導上面還有領導 private Handler nextHandler; //設置請假天數范圍 上不封頂 public Handler(int numStart) { this.numStart = numStart; } //設置請假天數范圍 public Handler(int numStart, int numEnd) { this.numStart = numStart; this.numEnd = numEnd; } //設置上級領導 public void setNextHandler(Handler nextHandler){ this.nextHandler = nextHandler; } //提交請假條 public final void submit(ILeave leave){ if(0 == this.numStart){ return; } //如果請假天數達到該領導者的處理要求 if(leave.getNum() >= this.numStart){ this.handleLeave(leave); //如果還有上級 並且請假天數超過了當前領導的處理范圍 if(null != this.nextHandler && leave.getNum() > numEnd){ this.nextHandler.submit(leave);//繼續提交 } } } //各級領導處理請假條方法 protected abstract void handleLeave(ILeave leave); }
小組長:
public class GroupLeader extends Handler { public GroupLeader() { //小組長處理1-3天的請假 super(Handler.NUM_ONE, Handler.NUM_THREE); } @Override protected void handleLeave(ILeave leave) { System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("小組長審批:同意。"); } }
部門經理:
public class Manager extends Handler { public Manager() { //部門經理處理3-7天的請假 super(Handler.NUM_THREE, Handler.NUM_SEVEN); } @Override protected void handleLeave(ILeave leave) { System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("部門經理審批:同意。"); } }
總經理:
public class BigManager extends Handler { public BigManager() { //部門經理處理7天以上的請假 super(Handler.NUM_SEVEN); } @Override protected void handleLeave(ILeave leave) { System.out.println(leave.getName() + "請假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("總經理審批:同意。"); } }
客戶端:
public static void main(String[] args) { //請假條來一張 ILeave leave = new Leave("小花",5,"身體不適"); //各位領導 Handler groupLeader = new GroupLeader(); Handler manager = new Manager(); Handler bigManager = new BigManager(); groupLeader.setNextHandler(manager);//小組長的領導是部門經理 manager.setNextHandler(bigManager);//部門經理的領導是總經理 //之所以在這里設置上級領導,是因為可以根據實際需求來更改設置,如果實戰中上級領導人都是固定的,則可以移到領導實現類中。 //提交申請 groupLeader.submit(leave); }
輸出:
小花請假5天,身體不適。
小組長審批:同意。
小花請假5天,身體不適。
部門經理審批:同意。
責任鏈模式
責任鏈模式:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將整個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它為止。
我們可以把各位領導想象成一條鏈,從鏈的開頭傳遞請求到盡頭,直到業務邏輯處理完成。
鏈上的每個節點都可以設置自己處理的指標范圍,也可以設置下一任處理者節點。
最顯著的好處就是請求者不用知道到底是哪個對象處理的,反正提交請求就對了。
同時鏈中的處理者並不知道整條鏈的結構,他們只需要保持一個指向下一任處理者對象的引用,這樣非常大的降低了耦合度。
責任鏈模式的缺點是性能問題,有可能一個請求是從整條鏈的頭部遍歷到鏈尾部,應該盡量避免超長鏈,並且如果出現問題,調試很不方便。