文章目錄
- 前言
- 正文
- 一、生活中的例子
- 二、Java代碼實現
- 2.1 類設計
- 2.2 代碼實現
- 2.2.1 Employee
- 2.2.2 ArchitectureDesignEmployer
- 2.2.3 BackEmployer
- 2.2.4 FrontEmployer
- 2.2.5 Leader
- 2.2.6 EmployeeStrongPointEnum
- 2.2.7 Boss
- 2.3 測試
- 2.3.1 Client
- 2.3.2 測試結果
- 三、委派模式的優缺點
- 3.1 優點
- 3.2 缺點
前言
委派模式(Delegate Pattern)又叫委托模式,是一種面向對象的設計模式。它不屬于23種設計模式之中,但同樣也應用廣泛。
熟悉java類加載的人都知道,java有一個雙親委派模型。就是應用了這個委派模式的思想。(但這不是我寫本文的原因!)
委派模式允許對象組合實現與繼承相同的代碼重用。它的基本作用就是負責任務的調用和分配任務,是一種特殊的靜態處理代理,可以理解為全權代理。
PS:寫本文的原因在于,前幾天看SpringMVC源碼時遇到過。
DispatcherServlet
的作用就是調節,分派請求。最終使用HandlerMapping
來處理這些請求。關于這個可以參考文章:《SpringMVC原理(設計原理+啟動原理+工作原理)》 的相關內容。
正文
一、生活中的例子
以生活中的例子,來研究何為委派模式。首先看一下這張圖:
一個簡單的模式,老板派發任務到經理,經理做協調,委派任務到各個不同崗位的人員。
二、Java代碼實現
在第一小節中的例子,使用java代碼對其進行設計并實現。
2.1 類設計
本次類的設計,使用類圖展示。
2.2 代碼實現
創建一個簡單的java項目,本次使用java8。
項目結構如下:
2.2.1 Employee
package org.feng;/*** 員工** @author feng*/
public interface Employee {/*** 處理任務接口** @param task 任務*/void handle(String task);
}
2.2.2 ArchitectureDesignEmployer
package org.feng;import java.util.Set;/*** 架構設計師** @author feng*/
public class ArchitectureDesignEmployer implements Employee {@Overridepublic void handle(String task) {printWords();System.out.printf("現在開始處理【%s】任務!%n", task);}private void printWords() {Set<String> strongPointSet = EmployeeStrongPointEnum.getStrongPointSet(this.getClass());System.out.printf("我是架構設計師,我擅長【%s】!%n", String.join(",", strongPointSet));}
}
2.2.3 BackEmployer
package org.feng;import java.util.Set;/*** 后端開發人員** @author feng*/
public class BackEmployer implements Employee {@Overridepublic void handle(String task) {printWords();System.out.printf("現在開始處理【%s】任務!%n", task);}private void printWords() {Set<String> strongPointSet = EmployeeStrongPointEnum.getStrongPointSet(this.getClass());System.out.printf("我是后端開發人員,我擅長【%s】!%n", String.join(",", strongPointSet));}
}
2.2.4 FrontEmployer
package org.feng;import java.util.Set;/*** 前端開發人員** @author feng*/
public class FrontEmployer implements Employee {@Overridepublic void handle(String task) {printWords();System.out.printf("現在開始處理【%s】任務!%n", task);}private void printWords() {Set<String> strongPointSet = EmployeeStrongPointEnum.getStrongPointSet(this.getClass());System.out.printf("我是前端開發人員,我擅長【%s】!%n", String.join(",", strongPointSet));}
}
2.2.5 Leader
package org.feng;import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;/*** 經理** @author feng*/
public class Leader implements Employee {private static final Map<String, Employee> EMPLOYEE_MAP;static {EMPLOYEE_MAP = new HashMap<>(16);try {initEmployeeMap();} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |IllegalAccessException e) {throw new RuntimeException(e);}}@Overridepublic void handle(String task) {if (!EMPLOYEE_MAP.containsKey(task)) {System.out.printf("這個任務【%s】,俺做不來!%n", task);return;}// 經理委派任務到其他員工EMPLOYEE_MAP.get(task).handle(task);}private static void initEmployeeMap() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {EmployeeStrongPointEnum[] strongPoints = EmployeeStrongPointEnum.values();for (EmployeeStrongPointEnum strongPoint : strongPoints) {Class<? extends Employee> employeeClass = strongPoint.getEmployeeClass();Employee employee = employeeClass.getDeclaredConstructor().newInstance();TreeSet<String> strongPointSet = strongPoint.getStrongPoints();for (String str : strongPointSet) {EMPLOYEE_MAP.put(str, employee);}}EMPLOYEE_MAP.forEach((k, v) -> {System.out.println("EMPLOYEE_MAP: task = " + k + ", emp = " + v);});System.out.println();}
}
2.2.6 EmployeeStrongPointEnum
package org.feng;import java.util.*;/*** 員工強項枚舉** @author feng*/
public enum EmployeeStrongPointEnum {ARCHITECTURE_DESIGN_EMPLOYER_STRONG_POINT(ArchitectureDesignEmployer.class, "架構設計", "架構優化"),FRONT_EMPLOYER_STRONG_POINT(FrontEmployer.class, "平面設計", "頁面修改", "頁面調整"),BACK_EMPLOYER_STRONG_POINT(BackEmployer.class, "數據庫設計", "后端功能開發", "后端功能修改");private final Class<? extends Employee> employeeClass;private final String[] strongPoints;EmployeeStrongPointEnum(Class<? extends Employee> employeeClass, String... strongPoints) {this.employeeClass = employeeClass;this.strongPoints = strongPoints;}public Class<? extends Employee> getEmployeeClass() {return employeeClass;}public TreeSet<String> getStrongPoints() {return new TreeSet<>(Arrays.asList(strongPoints));}private static final Map<Class<? extends Employee>, TreeSet<String>> EMP_STRONG_POINT_CACHE_MAP = new HashMap<>();static {for (EmployeeStrongPointEnum strongPointEnum : EmployeeStrongPointEnum.values()) {EMP_STRONG_POINT_CACHE_MAP.put(strongPointEnum.getEmployeeClass(), strongPointEnum.getStrongPoints());}}public static Set<String> getStrongPointSet(Class<? extends Employee> employeeClass) {TreeSet<String> treeSet = EMP_STRONG_POINT_CACHE_MAP.get(employeeClass);if(treeSet == null || treeSet.isEmpty()) {return Collections.emptySet();}return treeSet;}
}
2.2.7 Boss
package org.feng;/*** 老板** @author feng*/
public class Boss {/*** 委派任務到經理** @param task 任務* @param leader 經理*/public void delegateTask(String task, Leader leader) {leader.handle(task);}
}
2.3 測試
2.3.1 Client
package org.feng;/*** 測試** @author feng*/
public class Client {public static void main(String[] args) {Boss boss = new Boss();Leader leader = new Leader();boss.delegateTask("架構設計", leader);boss.delegateTask("頁面修改", leader);boss.delegateTask("測試頁面功能", leader);}
}
2.3.2 測試結果
EMPLOYEE_MAP: task = 后端功能開發, emp = org.feng.BackEmployer@448139f0
EMPLOYEE_MAP: task = 頁面修改, emp = org.feng.FrontEmployer@7cca494b
EMPLOYEE_MAP: task = 頁面調整, emp = org.feng.FrontEmployer@7cca494b
EMPLOYEE_MAP: task = 架構設計, emp = org.feng.ArchitectureDesignEmployer@7ba4f24f
EMPLOYEE_MAP: task = 平面設計, emp = org.feng.FrontEmployer@7cca494b
EMPLOYEE_MAP: task = 后端功能修改, emp = org.feng.BackEmployer@448139f0
EMPLOYEE_MAP: task = 架構優化, emp = org.feng.ArchitectureDesignEmployer@7ba4f24f
EMPLOYEE_MAP: task = 數據庫設計, emp = org.feng.BackEmployer@448139f0我是架構設計師,我擅長【架構優化,架構設計】!
現在開始處理【架構設計】任務!
我是前端開發人員,我擅長【平面設計,頁面修改,頁面調整】!
現在開始處理【頁面修改】任務!
這個任務【測試頁面功能】,俺做不來!
三、委派模式的優缺點
3.1 優點
通過任務委派能夠將一個大型的任務細化,然后通過統一管理這些子任務的完成情況實現任務的跟進,能夠加快任務執行的效率。
3.2 缺點
任務委派方式需要根據任務的復雜程度進行不同的改變,在任務比較復雜的情況下可能需要進行多重委派,容易造成絮亂。