当前位置: 首页 > news >正文

恩施哪里有做网站的企排排官网

恩施哪里有做网站的,企排排官网,谁知道苏州溪城水处理网站谁做的,莱芜区委网站09. 责任链模式 什么是责任链设计模式? 责任链设计模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理者对象组成的链进行传递,直到有一个处理者对象能够处理该请求为止。这种模式的目的…

09. 责任链模式

什么是责任链设计模式?

责任链设计模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理者对象组成的链进行传递,直到有一个处理者对象能够处理该请求为止。这种模式的目的是解耦请求的发送者和接收者,使得多个对象都有机会处理请求,从而增强了系统的灵活性。

责任链模式通常包含以下几个角色:

  1. 请求者(Client):发起请求的对象。
  2. 抽象处理者(Handler):定义一个处理请求的接口,通常包含一个方法用于处理请求,以及一个指向下一个处理者的引用。
  3. 具体处理者(Concrete Handler):实现抽象处理者接口的具体类,负责处理它所负责的请求,并决定是否将请求传递给链中的下一个处理者。
  4. 链(Chain):包含多个处理者对象,负责将请求沿着链传递。

责任链模式的工作原理如下:

  • 请求者创建一个请求并将其发送给链的起始处理者。

  • 每个处理者对象检查请求是否由自己处理。

    • 如果能够处理,则处理请求并结束责任链。
    • 如果不能处理,则将请求传递给链中的下一个处理者。
  • 这个过程一直持续,直到请求被处理或传递到链的末端。

责任链模式的优点包括:

  • 增强了系统的灵活性和可扩展性,因为可以动态地添加或移除处理者。
  • 降低了对象之间的耦合度,因为发送者和接收者不需要直接交互。
  • 允许多个对象处理同一个请求,增加了处理请求的灵活性。

责任链模式的缺点包括:

  • 请求的传递路径可能难以跟踪,尤其是在链很长或处理者逻辑复杂的情况下。
  • 责任链可能会导致系统性能问题,因为请求需要在多个对象之间传递。

责任链模式在实际应用中非常广泛,例如在GUI编程中处理事件、在网络编程中处理请求、在工作流系统中处理任务等场景。

举个简单的需求:

假如我们有个登录的场景,在登录处理流程中,需要校验参数、填充参数、登录判断、登录日志记录。我们每步都是环环相扣,此时就可以使用责任链模式。

有几个重要角色:

  • **Action:**责任链中的一个执行动作,主要定义具体执行动作,以及是否需要跳过。
  • **ActionChain:**责任链,用于定义添加执行动作方法,以及调度整条链路动作执行。
  • **ActionContext:**执行动作上下文,定义一个上下文对象,用来在链路执行过程中存储和传输数据。

将上面的步骤看做一个一个执行动作,建立对应的action,使用 chain 将多个 action 进行串联,同时我们可以定义一个context 上下文,用来在各个action之间传输数据。

除此之外,我们也可以通过配置中心,来定义哪些步骤需要执行,哪些可以跳过。

类图如下:

83CCDE77-5B01-46FF-882E-26C9DABFC5AB

代码编写:

1、定义顶级接口

(1)定义责任链执行动作上下文抽象类,用于责任链上下文之间数据传输。

@Data
public abstract class ActionContext implements Serializable, Cloneable {private static final long serialVersionUID = 1L;/*** 执行链名称,用于获取配置*/private String actionChainName;/*** 跳到结果处理*/private boolean isSkipToResult = false;public Object clone() throws CloneNotSupportedException {return super.clone();}
}

(2)定义责任链执行动作基类

public interface IAction<T extends ActionContext> {/*** 是否需要跳过* @param context 上下文* @return    true/false*/default boolean isSkippered(T context) throws Exception{if (context.isSkipToResult()) {return true;}// 通过配置中心获取是否需要执行List<String> config = ConfigServer.getConfig(context.getActionChainName());if (config.contains(getName())) {return false;}return true;}/*** 执行* @param context 上下文*/void execute(T context) throws Exception;/*** 获取执行动作名称,用于和配置中心进行匹配* @return*/String getName();} 

(3)定义Action 执行链接口

public interface IActionChain<T extends ActionContext> {/*** 添加一个Action* @param action 上下文* @return    action链*/IActionChain<T> appendAction(Class<? extends IAction<T>> action);IActionChain<T> appendActions(List<Class<? extends IAction<T>>> actions);IActionChain<T> appendAction(IAction<T> action);/*** 执行动作* @param context 上下文*/void execute(T context) throws Exception;
}

2、实现接口,定义具体的执行

(1)登录上下文

/*** 登录上下文*/
@EqualsAndHashCode(callSuper = true)
@Data
public class LoginActionContext extends ActionContext {/*** 失败日志*/private String failMsg;private String userName;private String password;private String token;private String ip;private String device;private Boolean isLoginFlag = true;
}

(2)定义责任链通用模版类

public class RouteActionChain<T extends ActionContext> implements IActionChain<T> {private List<IAction<T>> actionChain = new ArrayList<IAction<T>>();@Overridepublic IActionChain<T> appendAction(Class<? extends IAction<T>> action) {actionChain.add(getActionInstance(action));return this;}@Overridepublic IActionChain<T> appendActions(List<Class<? extends IAction<T>>> actions) {if (CollectionUtils.isEmpty(actions)) {return this;}for (Class<? extends IAction<T>> clazz : actions) {actionChain.add(getActionInstance(clazz));}return this;}@Overridepublic IActionChain<T> appendAction(IAction<T> action) {actionChain.add(action);return this;}@Overridepublic void execute(T context) throws Exception {for (IAction<T> action : actionChain) {//如果跳过 就不需要继续执行,这里顺序不能改变if (action.isSkippered(context)) {continue;}action.execute(context);}}public static <T extends ActionContext> IAction<T> getActionInstance(Class<? extends IAction<T>> clazz) {Collection<? extends IAction<T>> s = BeanUtil.getBeans(clazz);if (s != null && s.size() == 1) {return s.iterator().next();} else {throw new RuntimeException("action is not found");}}
}

(3)定义执行动作

  • 校验参数执行动作
  @Slf4j@Componentpublic class CheckParamAction implements IAction<LoginActionContext> {@Overridepublic void execute(LoginActionContext context) {// do somethinglog.info("CheckParamAction execute......");// 使用断言,判断用户名不为空try {Assert.isTrue(!StringUtils.isEmpty(context.getUserName()), "用户名不能为空");Assert.isTrue(!StringUtils.isEmpty(context.getPassword()), "密码不能为空");} catch (Exception e) {context.setIsLoginFlag(false);context.setSkipToResult(true);context.setFailMsg(e.getMessage());}}@Overridepublic String getName() {return "CheckParamAction";}}

填充参数执行动作

  @Slf4j@Componentpublic class FullParamAction implements IAction<LoginActionContext> {@Autowiredprivate ConfigServer configServer;@Overridepublic void execute(LoginActionContext context) throws Exception {log.info("FullParamAction execute......");// 使用断言,判断用户名不为空try {// do somethingcontext.setIp("127.0.0.1");context.setDevice("PC");context.setToken("123456");} catch (Exception e) {context.setIsLoginFlag(false);context.setSkipToResult(true);context.setFailMsg(e.getMessage());}}@Overridepublic String getName() {return "FullParamAction";}}
  • 登录判断执行动作
 @Slf4j@Componentpublic class LoginAction implements IAction<LoginActionContext> {@Overridepublic void execute(LoginActionContext context) throws Exception {// 模拟登录log.info("LoginAction execute......");try {// do somethingif(context.getUserName().equals(context.getPassword())) {context.setIsLoginFlag(true);} else {context.setIsLoginFlag(false);context.setFailMsg("用户名或密码输入错误");}} catch (Exception e) {context.setIsLoginFlag(false);context.setSkipToResult(true);context.setFailMsg(e.getMessage());}}@Overridepublic String getName() {return "LoginAction";}}
  • 登录日志记录执行动作
@Slf4j
@Component
public class LogAction implements IAction<LoginActionContext> {@Overridepublic void execute(LoginActionContext context) throws Exception {log.info("FullParamAction execute......");// 使用断言,判断用户名不为空try {// do somethinglog.info("数据库插入登录日志:{}", JSONObject.toJSONString(context));} catch (Exception e) {context.setIsLoginFlag(false);context.setSkipToResult(true);context.setFailMsg(e.getMessage());}}@Overridepublic String getName() {return "LogAction";}
}

(4)模拟配置中心

配置需要的执行动作,没有配置的自动跳过

@Component
@Data
public class ConfigServer {private static Map<String, List<String>> configMap = new HashMap<>();@PostConstructpublic void init(){ArrayList<String> configList = new ArrayList<>();configList.add("CheckParamAction");configList.add("FullParamAction");configList.add("LogAction");configList.add("LoginAction");configMap.put("login", configList);}/*** 获取配置列表* @param actionChainName* @return*/public static List<String> getConfig(String actionChainName) {return configMap.getOrDefault(actionChainName, new ArrayList<>());}
}

3、测试

定义测试接口

@Service
public class LoginServiceImpl implements LoginService {@Overridepublic boolean login(String userName, String password) {// 创建上下文LoginActionContext loginActionContext = new LoginActionContext();loginActionContext.setActionChainName("login");loginActionContext.setUserName(userName);loginActionContext.setPassword(password);// 构建责任链RouteActionChain<LoginActionContext> chain = new RouteActionChain<>();chain.appendAction(CheckParamAction.class);chain.appendAction(FullParamAction.class);chain.appendAction(LoginAction.class);chain.appendAction(LogAction.class);try {chain.execute(loginActionContext);} catch (Exception e) {throw new RuntimeException(e);}return loginActionContext.getIsLoginFlag();}
}

(1)测试正常情况,传输正确的 username 和 password。

A4D6064A-3712-400A-855A-2FB75697DCBC_4_5005_c

所有执行动作正常执行。

(2)测试异常情况, 传输错误的 username 和 password。

D94B82C6-1673-48DA-9493-EED41B96234B_4_5005_c

中间 LoginAction 执行失败,自动跳出责任链,后续执行动作未执行。

到此,一个简单的责任链设计模式的 demo 就已完成。

拓展点:

​ • 可以对接配置中心,动态定义不同业务逻辑中需要执行的动作。

​ • 可以将幂等性校验,添加到判断动作是否执行逻辑中。

http://www.zhongyajixie.com/news/5853.html

相关文章:

  • 极简风格网站介绍百度移动首页
  • 甘肃庆阳西峰区疫情开封网站快速排名优化
  • 免费空间asp网站网站有吗免费的
  • xydown wordpress网站搜索关键词优化
  • 高端建设网站公司哪家好常见的网络推广方式包括
  • 直接买个域名就能自己做网站百度云资源搜索网站
  • 龙湾网站建设免费网站seo排名优化
  • 网站开发设计文档模板网站推广的方法
  • 郑州网站推广排名快速seo关键词优化技巧
  • 黄江仿做网站全球最大的中文搜索引擎
  • 湖北可以做网站方案的公司无锡网站seo
  • 巴州建设局网站郑州纯手工seo
  • 邱县企业做网站推广产品市场营销策划方案
  • 招一个程序员可以做网站吗磁力宅在线搜种子
  • 广告公司做的网站图片侵权seo的推广技巧
  • 北京专业的做网站在线外链工具
  • 网站 高清 标清如何做浏览器下载安装2023版本
  • 网站SEO做点提升流量象客如何做一个网页
  • 自己做的网站如何让百度收录关键词可以分为哪三类
  • 邯山区建设局网站吉林黄页电话查询
  • 自媒体论坛交流推荐搜索引擎优化分析
  • 网站项目怎么做计划竞价推广怎么做
  • wordpress对接微信seo软文代写
  • 北京网页设计有限公司seo关键词优化
  • 免费的seo网站下载买卖链接网站
  • 如何做国外外贸网站营销型网站建设策划书
  • 免费建设网站制作seo公司的选上海百首网络
  • 网站购买外链制作网页链接
  • 溧阳城乡建设局网站如何在网上推广
  • 成都网站免费制作如何让自己网站排名提高