首页 > 其他分享 >说说设计模式~责任链模式

说说设计模式~责任链模式

时间:2023-06-28 10:12:54浏览次数:40  
标签:请求 处理 模式 Order 责任 Handler nextHandler 设计模式 order

回到目录

责任链模式

它是一种设计模块,主要将操作流程与具体操作解耦,让每个操作都可以设置自己的操作流程,这对于工作流应用是一个不错的选择!
下面是官方标准的定义:责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

使用场景

责任链模式在以下情况下可以被用到:

  1. 多个对象按照特定顺序依次处理请求:当存在多个对象需要依次处理请求,并且每个对象都有可能处理请求或将请求传递给下一个对象时,责任链模式可以很好地组织和管理这些对象。

  2. 需要动态指定处理对象:责任链模式可以通过动态设置责任链的关系,灵活地指定处理对象。可以根据实际情况动态增加、移除或调整处理者的顺序,而不需要修改客户端代码。

  3. 避免请求发送者和接收者之间的耦合关系:使用责任链模式可以将请求发送者和接收者解耦,发送者只需要将请求发送给责任链的第一个处理者,而不需要关心具体是哪个处理者来处理请求。

  4. 处理请求的对象需要进行动态配置:责任链模式可以通过配置文件、数据库等方式来动态配置处理者的顺序和条件,而不需要修改代码。

  5. 请求的处理逻辑具有变化和扩展的可能性:责任链模式可以很方便地对处理逻辑进行扩展和变化。可以通过增加新的处理者来扩展处理逻辑,也可以通过修改现有处理者的条件判断来变化处理逻辑。

一些常见的使用场景包括:

  • 客户端请求的处理:比如Web请求处理、日志记录、安全认证等。
  • 错误处理和异常处理:将异常或错误从一个处理者传递给下一个处理者进行处理,直到找到能够处理它的处理者。
  • 负载均衡:按照一定策略将请求传递给多个服务器进行处理,直到有服务器能够处理请求。
  • 事件驱动系统:通过触发事件并将事件传递给相关的处理者来实现事件的处理和响应。

需要注意的是,责任链模式并不保证一定会有处理者能够处理请求,因此需要在责任链末端进行处理请求无法被处理的情况。

实例中算法说明

  • 每种handler只使用一次
  • 按最高优先级去使用,符合就用,不符合就走下一个策略
  • 具体链条
    • VipHandler >10000
      • BigGiftHandler >1000
        • DiscountHandler >200
          • CouponHandler >100

代码实现

  • 定义处理请求的接口(Handler):
public interface Handler {

	void handleRequest(Order order);

	void setNextHandler(Handler nextHandler);

}
  • 具体处理请求CouponHandler
public class CouponHandler implements Handler {

	private static final Logger logger = LoggerFactory.getLogger(CouponHandler.class);

	private Handler nextHandler;

	@Override
	public void handleRequest(Order order) {
		// 这是可以想用多个责任链的实现,如果是只使用1个,需要加上200的限制,就是每个订单只能现用1种优惠
		if (order.getTotalPrice() >= 100) {
			// 应用优惠券打9折
			order.setTotalPrice(order.getTotalPrice() * .9);
			logger.info("Coupon 0.9 applied to order,{}", order.getOrderId());
		}else if (nextHandler != null) {
				nextHandler.handleRequest(order);
			}
	}

	public void setNextHandler(Handler nextHandler) {
		this.nextHandler = nextHandler;
	}

}
  • 具体处理请求DiscountHandler
 public class DiscountHandler implements Handler {

	private static final Logger logger = LoggerFactory.getLogger(CouponHandler.class);

	private static final double DISCOUNT = .8;

	private Handler nextHandler;

	@Override
	public void handleRequest(Order order) {
		if (order.getTotalPrice() >= 200) {
			// 应用折扣,折扣为标准的8折
			order.setTotalPrice(order.getTotalPrice() * DISCOUNT);
			logger.info("Discount 0.8 applied to order,{}", order.getOrderId());
		}
		else if (nextHandler != null) {
			nextHandler.handleRequest(order);
		}

	}

	public void setNextHandler(Handler nextHandler) {
		this.nextHandler = nextHandler;
	}

}

这个具体命令是可以扩展的,这也是职责链(责任链)的最重要的体现。

  • 命令模式,方便将命令之久,及后期的动态配置
@Data
@AllArgsConstructor
public class HandlerModel implements Comparable<HandlerModel> {

	private String title;

	private String classPath;

	private Integer sort;

	@Override
	public int compareTo(HandlerModel o) {
		return o.getSort() - this.sort; // 降序
	}

}
  • 命令工厂,这里使用了强编码的方式配置命令,真实项目中,这些命令可以配置到数据库中
/**
 * 折扣工厂.
 *
 * @author lind
 * @date 2023/6/28 9:22
 * @since 1.0.0
 */
public class HandlerFactory {

	public static Handler handlerFactory() {
		List<HandlerModel> handlerModels = new ArrayList<>();
		handlerModels.add(
				new HandlerModel("CouponHandler", "com.lind.common.pattern.chinaorder.handler.CouponHandler", 1));
		handlerModels.add(
				new HandlerModel("DiscountHandler", "com.lind.common.pattern.chinaorder.handler.DiscountHandler", 2));
		handlerModels.add(
				new HandlerModel("BigGiftHandler", "com.lind.common.pattern.chinaorder.handler.BigGiftHandler", 3));
		handlerModels.add(
				new HandlerModel("VipHandler", "com.lind.common.pattern.chinaorder.handler.VipHandler", 4));
		return createHandler(handlerModels);
	}

	private static Handler createHandler(List<HandlerModel> handlerModels) {
		Handler handler = null;
		Handler previousHandler = null;

		for (HandlerModel handlerModel : handlerModels.stream().sorted().collect(Collectors.toList())) {
			try {
				Handler currentHandler = (Handler) Class.forName(handlerModel.getClassPath()).newInstance();
				if (previousHandler != null) {
					previousHandler.setNextHandler(currentHandler);
				}
				else {
					handler = currentHandler;
				}
				previousHandler = currentHandler;
			}
			catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
				throw new RuntimeException(e);
			}
		}

		return handler;
	}

}
  • 看一下测试的代码
	public static void main(String[] args) {

		Handler couponHandler = HandlerFactory.handlerFactory();

		Order order1 = new Order("OR01", 150, true);
		couponHandler.handleRequest(order1);
		logger.info("order1:{}\n", order1.getTotalPrice());

		Order order2 = new Order("OR02", 250, true);
		couponHandler.handleRequest(order2);
		logger.info("order2:{}\n", order2.getTotalPrice());

		Order order3 = new Order("OR03", 50, true);
		couponHandler.handleRequest(order3);
		logger.info("order3:{}\n", order3.getTotalPrice());

		Order order4 = new Order("OR04", 5001, true);
		couponHandler.handleRequest(order4);
		logger.info("order4:{}\n", order4.getTotalPrice());

		Order order5 = new Order("OR05", 10001, true);
		couponHandler.handleRequest(order5);
		logger.info("order5:{}\n", order5.getTotalPrice());

待续……
回到目录

标签:请求,处理,模式,Order,责任,Handler,nextHandler,设计模式,order
From: https://www.cnblogs.com/lori/p/17510636.html

相关文章

  • 你用过哪些设计模式(一)?
    什么是设计模式?一些经验总结的最佳实践!是不是必须要用?并不是,但是既然已经说是最佳实践了,该用的地方,你不用,就有些违背常理了。一、单例这个或许是最最最常见,也是最最最常用的了。为什么要用单例模式?因为只需要一个对象就够了(有时候只能有一个,有时候是不需要有多个)。对象的......
  • 主窗口 模式打开窗口 UI刷新的测试
    窗体1定时器,标签,按钮。窗体1打开后,定时器自动运行,定时器每秒时间到,使得标签数值加1,点击按钮会打开窗体2。窗体2以模式方式打开,点击按钮会启动一次通讯请求。1-窗体1定时器,窗体2按钮触发同步通讯,窗体1的标签数值卡住不更新2-窗体1定时器,窗体2按钮触发异步通讯,窗体1的标签......
  • 基于Redis的消息发布和订阅(广播模式)
    最近在优化一个redis的大key问题,原先的同事写法是将所有的配置都放在一个key里面,value是一个map.但是随着配置越来越多,这个map也变得很大,已经影响redis的性能.遂决定将map里面的每个配置单独出来一个key,当有配置变动的时候,通过redis的消息队列通知到其他程序.下面......
  • 设计模式--适配器模式 Adapter
    设计模式 适配器模式Adapter 定义一个规则--->和尚吃斋念经打坐撞钟习武 缺省适配器模式 鲁智深鲁达形态丑陋面貌凶顽 此人上应天星心地刚直虽时下凶顽命中驳杂久后却得清净证果非凡汝等皆不及他 就是在一个接口跟正常子......
  • AT模式【分布式事务】
    1、导入maven依赖<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><!--版本较低,1.3.0,因此排除--><exclusion>......
  • 创建型模式-单例模式(使用元类实现)
    #创建型模式-单例模式(使用元类实现)#线程锁:防止创建多个实例#双重检查:实例创建后,防止重复加锁占用资源#__call__作用:__call__方法使一个类的实例像方法一样调用,当我们调用一个实例时,实际就是调用了它的__call__方法importtimefromthreadingimportLockfromconcurrent.futu......
  • 创建型模式-单例模式(使用类实现)
    importtimefromthreadingimportLockfromconcurrent.futuresimportThreadPoolExecutorclassTest():passclassSingleton():_local=Lock()_insrance=None@classmethoddefinstance(cls,*args,**kwargs):ifnotcls._i......
  • 创建型模式-单例模式(使用模块实现)
    singletion模块classTest():passa=Test() 调用模块fromsingleton.testimportaif__name__=="__main__":foriteminrange(10):b=aprint(id(b))......
  • 行为模式
    责任链模式责任链模式是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。比如kratos,gin等开源库的中间件实现。代码实现packagemainimport( "context" "fmt")typeHandlerfunc(ctxc......
  • 结构型模式
    适配器模式适配器模式用于转换一种接口适配另一种接口。比如,现在有个借口是对json字符串进行分析等,现在有一些yaml文件也要分析,这时候我我们就应该给yaml字符串就个适配器,转换成json字符串,然后就行分析。代码实现packagemainimport( "fmt" "github.com/ghodss/yaml")......