解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!

这篇具有很好参考价值的文章主要介绍了解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

委派模式

1.简述

委派模式是一种负责任务的调度和分配模式,类似于代理模式但更注重结果而非过程。它可以被视为一种特殊情况下的静态代理的全权代理,但并不属于GOF 23种设计模式之一,而是归类为行为型模式。

委派模式在Spring框架中广泛应用,其中最常见的例子是DispatcherServlet,它充分利用了委派模式的特性。

在Spring框架中,DispatcherServlet是一个核心组件,负责接收HTTP请求并将其分发给相应的处理器(Controller)进行处理。DispatcherServlet利用了委派模式的特性来实现请求的转发和处理。

具体来说,DispatcherServlet接收到HTTP请求后,根据请求的信息(如URL、请求方法等),会将请求委派给相应的处理器进行处理。这个委派的过程就是典型的委派模式应用。

在Spring中,DispatcherServlet并不直接处理请求,而是通过HandlerMapping确定请求对应的处理器(Controller),然后委派给对应的Controller进行处理。处理完成后,再由DispatcherServlet负责返回响应给客户端。

这种设计使得Spring的Web应用具有良好的灵活性和可扩展性。开发者可以根据自己的需求定制不同的HandlerMapping和Controller,而DispatcherServlet作为统一的入口,负责请求的委派和响应的处理,使得整个Web应用的架构更加清晰和易于维护。

应用场景

委派模式适用于以下场景:

  • 当需要实现表现层与业务层之间的松耦合时,委派模式能够提供一个良好的解决方案。
  • 在需要编排多个服务之间的调用时,特别是像责任链模式这样的情况下,委派模式尤为适用。
  • 当需要再封装一层服务查找和调用时,委派模式也是一种常见的选择。

优缺点

优点

  • 隐藏实现:对内部实现进行了封装,使得调用方不必关心具体的实现细节,增强了系统的安全性和稳定性。
  • 易于扩展:通过委派模式,可以方便地添加新的服务或功能,而不会影响到已有的代码。
  • 简化调用:调用方只需要知道委派对象,而不需要知道具体的执行细节,降低了系统的复杂度和维护成本。

缺点

  • 膨胀和管理难度:与静态代理相似,随着具体执行类和委派类的扩展,代码容易膨胀,难以管理,需要谨慎设计和维护。

业务场景示例

在关务系统中,费用计算是一个关键功能。不同部门可能采用不同的计算方式。为了应对这种多样性,系统需要根据不同部门的要求,动态选择合适的费用计算算法,以确保费用的准确性和合规性。

在这样的场景下,可以借助委派模式来实现动态选择合适的计算算法。下面,我们以Spring Boot版本的委派模式为例来展示其具体实现。

2.类图

解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!,spring boot,设计模式,后端,java

3.具体实现

3.1.自定义注解

import java.lang.annotation.*;

@Documented
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Delegate {

	/**
	 * 执行任务类型
	 */
	String type () default "";
}

3.2.定义抽象委派接口

/**
 * 委派任务通用处理接口
 */
public interface DelegateHandler<R,T> {

	/**
	 * 抽象处理方法
	 * @param t 处理任务参数
	 */
	R process(T t);
}

3.3.定义具体执行者

/**
 * 财务部门委派类
 * @author 13723
 * @version 1.0
 * 2024/1/7 14:52
 */
@Delegate(type = "finance")
@Component
public class FinanceDepartmentDelegate implements DelegateHandler<ResultObject, BigDecimal>{
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

	/**
	 * 财务部门处理(将数据加上税费)
	 * @param s 处理任务参数
	 * @return
	 */
	@Override
	public ResultObject process(BigDecimal s) {
		ResultObject instance = ResultObject.createInstance(true);
		BigDecimal res = BigDecimal.ZERO;
		if (s != null) {
			res = s.add(new BigDecimal("300"));
			instance.setData(res);
		}
		instance.setMessage("财务部门处理数据结束!");
		logger.error("财务部门处理数据结束!处理前:{},处理后:{}",s,res);
		return instance;
	}
}






/**
 * 生产部门委派类
 * @author 13723
 * @version 1.0
 * 2024/1/7 14:44
 */
@Delegate(type = "product")
@Component
public class ProductionDepartmentDelegate implements DelegateHandler<ResultObject, BigDecimal> {
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());


	/**
	 * 生产部门处理(将数据重新计算)
	 * @param s 处理任务参数
	 * @return
	 */
	@Override
	public ResultObject process(BigDecimal s) {
		ResultObject instance = ResultObject.createInstance(true);
		BigDecimal res = BigDecimal.ZERO;
		if (s != null) {
			res = s.multiply(new BigDecimal("1.6"));
			instance.setData(res);
		}
		instance.setMessage("生产部门处理数据结束!");
		logger.error("生产部门处理数据结束!处理前:{},处理后:{}",s,res);
		return instance;
	}
}

3.4.定义委派者(统一管理委派任务)

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.CollectionUtils;

import java.lang.invoke.MethodHandles;
import java.util.*;

/**
 *  委派角色管理类
 * @author 13723
 * @version 1.0
 * 2024/1/7 14:58
 */
@Delegate
public class DelegateManager extends DelegatePatternConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

	/**
	 * 存放具体委派角色类型
	 * k-具体委派类型
	 * v-具体任务角色
	 */
	private Map<String, List<DelegateHandler>> handlerMap;

	/**
	 * 存放委派模式中的各种真正执行任务的角色
	 * 分组放
	 * @param iHandlerList
	 */
	public void setHandlerMap(List<DelegateHandler> iHandlerList) {
		handlerMap = scanHandlers(iHandlerList);
	}

	/**
	 * 将具体的委派角色 获取进行统一管理
	 * @param handlerList 具体实现委派的类集合
	 * @return 存放委派
	 */
	private Map<String, List<DelegateHandler>> scanHandlers(List<DelegateHandler> handlerList) {
		ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
		scanner.addIncludeFilter(new AnnotationTypeFilter(Delegate.class));
		Map<String, List<DelegateHandler>> handlerMap = new HashMap<>();
		for (DelegateHandler handler : handlerList) {
			Class<?> targetClass = handler.getClass();
			if (hasDutyAnnotation(targetClass)) {
				String type = getTypeAnnotationValue(targetClass);
				handlerMap.computeIfAbsent(type, key -> new ArrayList<>()).add(handler);
			}
		}
		return handlerMap;
	}
    
	/**
	 * 判断该类是否是 使用使用了Delegate注解
	 * @param clazz 类名称
	 * @return true使用了
	 */
	private boolean hasDutyAnnotation(Class<?> clazz ) {
		return AnnotationUtils.findAnnotation(clazz, Delegate.class) != null;
	}

	/**
	 * 判断使用了的注解@Delegate 是否填写了类型
	 * @param clazz
	 * @return
	 */
	private String getTypeAnnotationValue(Class<?> clazz) {
		Delegate dutyAnnotation = AnnotationUtils.findAnnotation(clazz, Delegate.class);
		if (dutyAnnotation == null) {
			throw new IllegalStateException("Delegate annotation not found for class: " + clazz);
		}
		return dutyAnnotation.type();
	}


	/**
	 * 根据类型 委派具体执行任务的角色
	 * @param type 任务类型
	 * @param t 传递参数
	 * @return 执行后 最终返回结果
	 */
	public <R, T> R process(String type, T t) {
		List<DelegateHandler> handlers = handlerMap.get(type);
		R result = null;
		if (!CollectionUtils.isEmpty(handlers)) {
			// 注意 这里需要考虑多个执行角色问题,遇到多个相同类型执行角色,考虑使用责任链,别再此模式上死磕。
			for (DelegateHandler<R, T> handler : handlers) {
				result = handler.process(t);
			}
		}else {
			throw new RuntimeException("no match delegate class !");
		}
		return result;
	}
}

3.5.定义委派者管理类

/**
 * 将 委派模式管理类 注入到Spring中
 * @author 13723
 * @version 1.0
 * 2024/1/7 15:16
 */
@Configuration
public class DelegatePatternConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

	@Bean
	public DelegateManager delegateManager(List<DelegateHandler> handlers) {
		// 创建对象 会获取全部使用注解的类,将其注入到对应map集合中
		DelegateManager delegateManager = new DelegateManager();
		delegateManager.setHandlerMap(handlers);
		return delegateManager;
	}
}

4.测试

4.1.controller层

import com.hrfan.java_se_base.config.ResultObject;
import com.hrfan.java_se_base.pattern.decorator_pattern.config.DecorateManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.lang.invoke.MethodHandles;
import java.math.BigDecimal;
import java.util.Objects;

/**
 * 委派模式测试类
 * @author 13723
 * @version 1.0
 * 2024/1/7 15:20
 */
@RestController
@RequestMapping("/v1/delegate")
public class DelegateTestController {
	@Resource
	private DelegateService service;
	private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

	@Resource
	DelegateManager manager;

	@PostMapping("/test")
	public ResultObject test(@RequestBody DelegateMoneyParams params){
		ResultObject instance = ResultObject.createInstance(false);
		instance.setMessage("计算失败!");
		Objects.requireNonNull(params);
		if (StringUtils.isNotBlank(params.getType())){
			switch (params.getType()){
				case "a":
					instance =  manager.process("product", params.getTotal());
					return instance;
				case "b":
					instance =  manager.process("finance", params.getTotal());
					return instance;
				default:
					return instance;
			}
		}
		return instance;
	}
}

4.2.测试不同场景

4.2.1.测试生产部门计算费用

解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!,spring boot,设计模式,后端,java

4.2.2.测试财务部门计算费用

解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!,spring boot,设计模式,后端,java

4.2.3.测试各种类型传值

解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!,spring boot,设计模式,后端,java

解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!,spring boot,设计模式,后端,java文章来源地址https://www.toymoban.com/news/detail-825973.html

到了这里,关于解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring】Spring中的设计模式

    责任链模式介绍 Spring源码介绍 spring中Aop的责任链模式,相对于传统的责任链模式做了一定的改造。 传统的设计模式,抽象处理者会有一个方法设置和获取具体处理者的下一个处理者的方法。 如: 但是Spring中的责任链模式没有这两个方法,而是抽出一个公共的处理方法,方

    2024年02月14日
    浏览(41)
  • Spring中的设计模式

    目录 1.Spring中使用到的设计模式有: 2.工厂模式 3.单例模式 4.代理模式 5.模板模式 6.适配器模式         工厂模式:实现IoC容器         单例模式:将bean设置为单例         代理模式:AOP的底层实现         模板模式:比如引入jdbc依赖后出现的jdbcTemplate         适配器模

    2024年02月12日
    浏览(45)
  • JAVA设计模式第七讲:设计模式在 Spring 源码中的应用

    设计模式(design pattern)是对软件设计中普遍存在的各种问题,所提出的解决方案。本文以面试题作为切入点,介绍了设计模式的常见问题。 我们需要掌握各种设计模式的原理、实现、设计意图和应用场景,搞清楚能解决什么问题 。 本文是第七篇:设计模式在 Spring 源码中的

    2024年02月09日
    浏览(44)
  • Spring框架中的8种设计模式

    前言 Spring框架中的8种设计模式分别是: 1、简单工厂。2、工厂方法。3、单例模式。4、适配器模 式。5、装饰器模式。6、代理模式。7、观察者模式。8、策略模式. 1、简单工厂 Spring中的 BeanFactory 就是简单工厂模式的体现, 根据传入一个唯一的标识来获得Bean对象 , 但是否在

    2024年02月05日
    浏览(43)
  • 探索设计模式的魅力:掌握命令模式-解锁软件设计的‘遥控器’

    ​🌈 个人主页: danci_ 🔥 系列专栏: 《设计模式》 💪🏻 制定明确可量化的目标,并且坚持默默的做事。 引言:探索命令模式的奥秘     软件设计领域充满挑战与机遇,命令模式作为关键要素,以优雅方式组织应用程序中的行为和请求。命令模式在现实世界中无处不在

    2024年02月20日
    浏览(55)
  • 创建型设计模式03-原型模式

    🧑‍💻作者:猫十二懿 🏡账号:CSDN 、个人博客 、Github 🎊公众号:猫十二懿 原型模式是一种创建型设计模式,它允许通过复制现有对象来生成新对象,而无需编写从头开始创建新对象的代码。 1.1 具体介绍 在原型模式中,我们首先创建一个原型对象,然后通过复制该对象

    2024年02月06日
    浏览(43)
  • 03-JAVA设计模式-命令模式

    命令模式(Command Pattern)是一种行为设计模式,它将请求封装为对象,从而使你可用不同的请求把客户端与请求的处理者解耦,也称动作模式或事物模式。 在命令模式中,命令对象封装了接收者对象的动作,调用者通过调用命令对象来执行该动作,而无需知道具体的接收者对

    2024年04月27日
    浏览(33)
  • 03-JAVA设计模式-组合模式

    组合模式(Composite Pattern)允许你将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端以统一的方式处理单个对象和对象的组合。组合模式让你可以将对象组合成树形结构,并且能像单独对象一样使用它们。 把部分和整体的关系用树形结构来表示,从而是客户

    2024年04月11日
    浏览(53)
  • 03-JAVA设计模式-建造者模式

    建造者模式(Builder Pattern)是一种对象构建的设计模式,它允许你通过一步一步地构建一个复杂对象,来隐藏复杂对象的创建细节。 这种模式将一个复杂对象的构建过程与其表示过程分离,使得同样的构建过程可以创建不同的表示。命名建议以Builder结尾,以达到见名之意。

    2024年04月15日
    浏览(61)
  • 03-JAVA设计模式-适配器模式

    它属于结构型模式,主要用于将一个类的接口转换成客户端所期望的另一种接口,从而使得原本由于接口不兼容而无法协同工作的类能够一起工作。 适配器模式主要解决的是不兼容接口的问题。在软件开发中,经常会有这样的情况:我们有一个现有的类,它的接口(方法、属

    2024年04月09日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包