文章目录
- 前言
- 正文
- 一、生活中的例子
- 二、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 缺点
任务委派方式需要根据任务的复杂程度进行不同的改变,在任务比较复杂的情况下可能需要进行多重委派,容易造成絮乱。