设计模式之委派模式

news2024/9/22 7:25:19

文章目录

  • 前言
  • 正文
    • 一、生活中的例子
    • 二、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.coloradmin.cn/o/1464434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hackme 1

信息收集 Nmap部分 存活扫描&#xff1a; └─# nmap -sn 192.168.10.1/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-02-20 15:00 CST Nmap scan report for 192.168.10.1 (192.168.10.1) Host is up (0.00012s latency). MAC Address: 00:50:56:C0:00:08 (VMwar…

【vue js】将数组元素,按照2个一组,重组为2维数组

实现效果&#xff1a; 要实现上述&#xff0c;2张图片为一个走马灯的内容&#xff0c;而后端传回的数据是一个数组。我采用的是将数据重组为2维数组的方法。 因为没有强制要求展示顺序&#xff0c;我采用将首尾组合的方式组成一个数组元素&#xff1b; 首先判断原始数据长度的…

onnx 1.16 doc学习笔记四:python API-If和Scan

onnx作为一个通用格式&#xff0c;很少有中文教程&#xff0c;因此开一篇文章对onnx 1.16文档进行翻译与进一步解释&#xff0c; onnx 1.16官方文档&#xff1a;https://onnx.ai/onnx/intro/index.html](https://onnx.ai/onnx/intro/index.html)&#xff0c; 如果觉得有收获&am…

$attrs

一、概念 vue官网定义如下: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过v-bind="$attrs"传入内部组件——在创建…

【高德地图】Android高德地图控件交互详细介绍

&#x1f4d6;第5章 与地图控件交互 ✅控件交互&#x1f9ca;缩放按钮&#x1f9ca;指南针&#x1f9ca;定位按钮&#x1f9ca;地图Logo ✅手势交互&#x1f9ca;缩放手势&#x1f9ca;滑动手势&#x1f9ca;旋转手势&#x1f9ca;倾斜手势&#x1f9ca;指定屏幕中心点的手势操…

无线传感器网络简单介绍

&#xff08;本文为简单介绍&#xff0c;内容来源自网络&#xff09; 无线传感器网络&#xff08;Wireless Sensor Networks&#xff09;是一种创新的传感器网络架构&#xff0c;具有广泛的应用前景和潜力。与传统的有限传感器网络不同&#xff0c;无线传感器网络克服了节点数…

在苹果电脑MAC上安装Windows10(双系统安装的详细图文步骤教程)

在苹果电脑MAC上安装Windows10&#xff08;双系统安装的详细图文步骤教程&#xff09; 一、准备工作准备项1&#xff1a;U盘作为系统安装盘准备项2&#xff1a;您需要安装的系统镜像 二、启动转换助理步骤1&#xff1a;找到启动转换助理步骤2&#xff1a;启动转换助理步骤3&…

基于springboot+vue的安康旅游网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

【Java EE初阶二十】http的简单理解(一)

1. 初识http HTTP 最新的版本应该是 HTTP/3.0&#xff0c;目前大规模使用的版本 HTTP/1.1&#xff1b; 下面来简单说明一下使用 HTTP 协议的场景: 1、浏览器打开网站 (基本上) 2、手机 APP 访问对应的服务器 (大概率) 前面的 TCP与UDP 和http不同&#xff0c;HTTP 的报文格式&a…

基于Embedding召回和DSSM双塔模型

文章目录 基于Embedding召回介绍基于Embedding召回算法分类I2I召回U2I召回 DSSM模型DSSM双塔模型层次 基于Embedding召回介绍 基于embedding的召回是从内容文本信息和用户查询的角度出发&#xff0c;利用预训练的词向量模型或深度学习模型&#xff0c;将文本信息转换成向量进行…

【PyQt】15-让控件支持拖拽工作

文章目录 前言一、控件的拖拽-setAcceptDrops()1.1 代码1.2 运行结果 总结 前言 允许控件的拖拽操作&#xff0c;后续可以升级为拖拽图片之类的。hasHtml()、hasUrls()、hasImage() 一、控件的拖拽-setAcceptDrops() 比如把A放到B&#xff0c;需要两步 B—setAcceptDrops(Tru…

Hudi程序导致集群RPC偏高问题分析

1、背景 Hudi程序中upsert操作频繁&#xff0c;过多的删除和回滚操作,导致集群RPC持续偏高 2、描述 hudi采用的是mvcc设计&#xff0c;提供了清理工具cleaner来把旧版本的文件分片删除&#xff0c;默认开启了清理功能&#xff0c;可以防止文件系统的存储空间和文件数量的无限…

【自然语言处理】:实验5,司法阅读理解

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 代码和报告均为本人自己实现&#xff08;实验满分&#xff09;&#xff0c;只展示主要任务实验结果&#xff0c;如果需要详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢…

配置redis-cell 控流插件

1.下载绑定资源也可以到git上下载 https://gitee.com/dianjinshi/springboot-nginx.git 2.创建文件夹 mkdir redis-cell 3.上传到linux上并进入文件夹解压 4.拷贝 docker cp libredis_cell.so redis:/usr/local/etc/redis 5.重启redis docker restart redis 6.进入redis…

六、回归与聚类算法 - 欠拟合和过拟合

目录 1、定义 2、原因及解决方法 2.1 正则化 线性回归欠拟合与过拟合线性回归的改进 - 岭回归分类算法&#xff1a;逻辑回归模型保存与加载无监督学习&#xff1a;K-means算法 1、定义 2、原因及解决方法 2.1 正则化

【Emgu CV教程】7.3、图像锐化之手搓代码实现直方图均衡化

文章目录 一、介绍1.写在前面2.彩色图像直方图均衡化函数 二、举例 一、介绍 1.写在前面 上一篇文章介绍的是直方图均衡化&#xff0c;使用Emgu CV的EqualizeHist()函数。它对于背景和前景都太亮或者太暗的图像非常有用&#xff0c;而且计算速度非常快&#xff0c;简单又好用…

NXP实战笔记(七):S32K3xx基于RTD-SDK在S32DS上配置ICU输入捕获

目录 1、概述 2、输入捕获SDK配置 2.1、SAIC中断方式 2.2、IPWM或者IPM 1、概述 输入捕获&#xff0c;可以抓取高电平时间、低电平时间、占空比、周期、边沿检测与回调函数、边沿计数&#xff08;ABZ解码&#xff09;、时间戳、唤醒中断。 记录一下根据Emios模块实现上述部分…

论文精读--word2vec

word2vec从大量文本语料中以无监督方式学习语义知识&#xff0c;是用来生成词向量的工具 把文本分散嵌入到另一个离散空间&#xff0c;称作分布式表示&#xff0c;又称为词嵌入&#xff08;word embedding&#xff09;或词向量 Abstract We propose two novel model architec…

LeetCode 热题 100 | 二叉树(终)

目录 1 二叉树小结 1.1 模式一 1.2 模式二 2 236. 二叉树的最近公共祖先 3 124. 二叉树中的最大路径和 菜鸟做题&#xff08;返校版&#xff09;&#xff0c;语言是 C 1 二叉树小结 菜鸟碎碎念 通过对二叉树的练习&#xff0c;我对 “递归” 有了一些肤浅的理解。…

适用于 Windows 10、11 的 5 款最佳免费文件恢复软件

最好的免费文件恢复软件是什么&#xff1f; 如今&#xff0c;人们通常将数据保存在硬盘或云备份上。除此之外&#xff0c;您还可以将重要数据存储在 USB 或其他电子设备上。 但是&#xff0c;如果您遇到存储设备故障、存储设备逻辑故障或意外删除&#xff0c;您可能会丢失文件…