设计模式之委派模式

文章目录

  • 前言
  • 正文
    • 一、生活中的例子
    • 二、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 {
    @Override
    public 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 {
    @Override
    public 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 {
    @Override
    public 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);
        }
    }

    @Override
    public 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 缺点

任务委派方式需要根据任务的复杂程度进行不同的改变,在任务比较复杂的情况下可能需要进行多重委派,容易造成絮乱。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/396258.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL Developer 小贴士:显示RAC配置

前提&#xff1a; 已建立2节点RAC已在SQL Developer中建立了2个连接&#xff0c;分别到RAC的两个节点 然后单击菜单View>DBA&#xff0c;分别连接RAC节点1和节点2&#xff0c;并组织成目录&#xff08;不必须&#xff0c;但建议&#xff09;。 在两处可以体现为RAC配置。第…

Keepalived实现Nginx的高可用集群案例

服务器规划: serverb(nginx2):192.168.233.144 serverc(客户端):192.168.233.140 serverd(nginx1):192.168.233.141 结构图: serverd(nginx1): # 安装nginx yum install nginx -y# 进入nginx配置目录 cd /e…

【安全狐】Windows隐藏计划任务技术及排查方法

0x00 前置知识 计划任务SCHTASKS命令 SCHTASKSSCHTASKS /Create 参数 SCHTASKS /Create [/S system [/U username [/P [password]]]][/RU username [/RP password]] /SC schedule [/MO modifier] [/D day][/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttim…

【MATLAB源码-第141期】基于matlab的免疫优化算法在物流配送中心选址应用仿真,输出选址图以及算法适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 免疫优化算法在物流配送中心选址中的应用是一个集成了信息科学、生物学原理和运筹学的跨学科研究领域。本文旨在探讨免疫优化算法在物流配送中心选址问题中的应用&#xff0c;包括算法的基本原理、模型构建、算法实现及其在实…

华为配置旁挂二层组网隧道转发示例

配置旁挂二层组网隧道转发示例 组网图形 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件扩展阅读 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响用户的业务使用。 组网需求 AC组…

GPIO控制和命名规则

Linux提供了GPIO子系统驱动框架&#xff0c;使用该驱动框架即可灵活地控制板子上的GPIO。 GPIO命名 泰山派开发板板载了一个40PIN 2.54间距的贴片排针&#xff0c;排针的引脚定义兼容经典40PIN接口。 在后续对GPIO进行操作前&#xff0c;我们需要先了解k3566的GPIO命名规则&a…

Sublime替换文本中的换行/回车符等特殊符号

1、快捷键打开查找替换&#xff08;windows&#xff09; Ctrl h 2、开启打开查找窗口最左侧的(.*)正则匹配功能&#xff0c;上图中箭头所指。 3、Find栏输出被替换的正则表达式&#xff0c;如\n 回车符&#xff0c;表达式会有颜色显示 4、Replace栏输入替换后的内容&#xff0…

第8章 对同步的硬件支持

为了保证并行程序执行的正确性和高效性&#xff0c;构建一个共享存储多处理器系统的硬件支持必须要解决缓存一致性、存储一致性和对同步原语的支持等问题。从软件的观点来看被广泛使用的同步原语包括锁、栅栏和点对点同步&#xff08;信号量&#xff09;。举例来说&#xff0c;…

用于将Grafana默认数据库sqlite3迁移到MySQL数据库

以下是一个方案&#xff0c;用于将Grafana数据迁移到MySQL数据库。 背景: grafana 默认采用的是sqlite3&#xff0c;当我们要以集群形式部署的时使用mysql较为方便&#xff0c;试了很多sqlite转mysql的方法要么收费,最后放弃。选择自己动手风衣足食。 目标: 迁移sqlite3切换…

Vue报错,xxx is defined #变量未定义

vue.js:5129 [Vue warn]: Error in v-on handler: "ReferenceError: count is not defined" 浏览器将这个变量 当做全局变量了&#xff0c;事实上它只是实例中的变量 加上this指定&#xff0c;是vue实例中的变量

进程链信任-父进程欺骗

文章目录 前记普通权限的父进程欺骗ShllCode上线进程提权基础进程提权注入 前记 父进程欺骗作用&#xff1a; 进程链信任免杀进程提权 检测&#xff1a; etw 普通权限的父进程欺骗 #include<stdio.h> #include<windows.h> #include <TlHelp32.h>DWORD …

跳过测试方法(测试类)(@Ignore)

1.什么情况下要使用跳过测试(测试类)方法? 写了一个测试方法但是不想执行 删掉该测试方法&#xff08;测试类&#xff09;注释该测试方法&#xff08;测试类&#xff09;使用Ignore注解 2.示例 2.1 必要工作 导入类库 import org.junit.Ignore; 2.2 使用Ignore注解跳过…

gin源码实战 day1

gin框架源码实战day1 Radix树 这个路由信息&#xff1a; r : gin.Default()r.GET("/", func1) r.GET("/search/", func2) r.GET("/support/", func3) r.GET("/blog/", func4) r.GET("/blog/:post/", func5) r.GET("/…

Web3区块链游戏:创造虚拟世界的全新体验

随着区块链技术的不断发展&#xff0c;Web3区块链游戏正逐渐崭露头角&#xff0c;为玩家带来了全新的虚拟世界体验。传统游戏中的中心化结构和封闭经济体系已经被打破&#xff0c;取而代之的是去中心化的游戏环境和真实所有权的数字资产。本文将深入探讨Web3区块链游戏的特点、…

Python Selenium实现自动化测试及Chrome驱动使用

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站零基础入门的AI学习网站~。 目录 ​编辑 前言 Selenium简介 安装Selenium库 编写自动化测试脚本 1 打开浏览器并访问网页 2 查找页面元…

[力扣 Hot100]Day30 两两交换链表中的节点

题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 出处 思路 前两个结点先偷一手用交换val做&#xff0c;从链表第1…

对视频进行分块,断点续传

分块测试 //分块测试Testpublic void testChunk() throws IOException {//源路径File sourceFile new File("D:\\BaiduNetdiskDownload\\Day1-00.项目导学.mp4");//分块文件存储路径String chunkFilePath "D:\\develop\\chunk\\";//分块文件大小int chun…

XR行业首家|李未可科技通过深度合成服务算法备案

2月18日&#xff0c;国家网信办发布第四批深度合成服务算法备案。 根据《互联网信息服务深度合成管理规定》第十九条规定&#xff0c;具有舆论属性或者社会动员能力的深度合成服务提供者&#xff0c;应当按照《互联网信息服务算法推荐管理规定》履行备案和变更、注销备案手续。…

(十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)

简述 操作路径如下: 作用:通过逐步增加线程数来模拟用户并发访问。配置:设置This group will start、First,wait for 、Then start、Next , add等参数。使用场景:模拟逐步增长的并发访问,观察应用程序的性能变化。优点:适用于测试应用程序在逐步增加负载下的性能表现。…
最新文章