ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前端设计模式(七):责任链模式

2022-07-01 16:04:25  阅读:161  来源: 互联网

标签:function const 前端 责任 handler params new return 设计模式


参考文章:

​ 在日常业务开发中,你可能会常常去校验一个参数或者过滤一些对象,在各种if(判断条件){执行这个分支逻辑} 后,你的代码会越来越臃肿,责任链模式就是为了解决这个问题,让业务逻辑解耦合,可扩展

​ 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

示意图:

image

用职责链模式改进后:

image

责任链的类实现方式:


/**
 * 定义参数校验抽象类,指定行为,确定每个链通用逻辑
 */
class AbstractParamsChainHandler {

  constructor() {
    this.nextHandler = null;
  }

  setNextHandler(nextHandler) {
    this.nextHandler = nextHandler;
  }

  getNextHandler() {
    return this.nextHandler;
  }

  doValidate(params){
    throw new Error('必须由子类重写的验证方法');
  }

  executeValidateChain(params){
    let validate_result = this.doValidate(params);
    if(!validate_result) return;
    if (this.getNextHandler){
      this.getNextHandler()?.executeValidateChain.call(this.getNextHandler(),params);
    }
  }
}

/**
 * 空参数校验
 */
class EmptyCheckHandler extends AbstractParamsChainHandler {

  doValidate(params) {
    if(['', undefined, null].includes(params)){
      console.log('EmptyCheckHandler: 当前参数为空,校验不通过');
      return false
    }

    return true
  }
}

/**
 * 参数不能包含空格校验
 */
class WhiteSpaceCheckHandler extends AbstractParamsChainHandler {

  doValidate(params) {
    if(/\s+/g.test(params)){
      console.log('EmptyCheckHandler: 当前参数包含空格,校验不通过');
      return false
    }

    return true
  }
}

/**
 * 不能超过指定长度
 */
class WordLengthCheckHandler extends AbstractParamsChainHandler {

  constructor(wordLength) {
    super();
    this.wordLength = wordLength
  }

  doValidate(params) {
    if(params.length > this.wordLength){
      console.log(`WordLengthCheckHandler: 长度校验不通过,当前文字长度: ${params.length},限制的长度: ${this.wordLength}`);
      return false
    }
    return true
  }
}

class ParamsCheckService {

  /**
   * 假设对用户名进行监测
   * @param name
   */
  static userNameCheck(name){
    const empty_handler = new EmptyCheckHandler();
    const whitespace_handler = new WhiteSpaceCheckHandler();
    const word_handler = new WordLengthCheckHandler(5);

    empty_handler.setNextHandler(word_handler);
    word_handler.setNextHandler(whitespace_handler);

    empty_handler.executeValidateChain(name);
  }
}

ParamsCheckService.userNameCheck('')

function实现方式

以打印日志等级为例,探索函数式的实现方式

1.我们先实现一个 Handler 对象,构建链条:

const Handler = function (fn) {
    this.handler = fn;
    this.next = null;
};
 
Handler.prototype.setNext = function setNext(h) {
    this.next = h;
    return h;
};
 
Handler.prototype.passRequest = function () {
    const ret = this.handler.apply(this, arguments);
    this.next && this.next.passRequest.apply(this.next, arguments);
};

2.接下来实现不同的 Logger

const ERR = 3;
const NOTICE = 5;
const DEBUG = 7;
 
const StdoutLogger = function (msg, level) {
    // 根据等级判断自己是否处理
    if (level <= DEBUG) {
        console.log("Writting to stdout: " + msg);
    }
};
 
const EmailLogger = function (msg, level) {
   // 根据等级判断自己是否处理
    if (level <= NOTICE) {
        console.log("Sending via email: " + msg);
    }
};
 
const StderrLogger = function (msg, level) {
   // 根据等级判断自己是否处理
    if (level <= ERR) {
        console.log("Sending to stderr: " + msg);
    }
};

3.测试

const StdoutHandler = new Handler(StdoutLogger);
const EmailHandler = new Handler(EmailLogger);
const StderrHandler = new Handler(StderrLogger);
StdoutHandler.setNext(EmailHandler).setNext(StderrHandler);
 
StdoutHandler.passRequest("Entering function y.", DEBUG);
StdoutHandler.passRequest("Step1 completed.", NOTICE);
StdoutHandler.passRequest("An error has occurred.", ERR);
链式函数再职责链中的运用

这个例子来自于《JavaScript高级程序设计第四版》,下面是部分代码

Function.prototype.after = function( fn ){ 
	var self = this; 
	return function(){ 
        var ret = self.apply( this, arguments ); 
        if ( ret === 'nextSuccessor' ){ 
            return fn.apply( this, arguments ); 
        } 
            return ret; 
 	} 
};

用职责链模式获取文件上传对象

var getActiveUploadObj = function () {
    try {
        return new ActiveXObject("TXFTNActiveX.FTNUpload"); // IE 上传控件
    } catch (e) {
        return 'nextSuccessor';
    }
};

var getFlashUploadObj = function () {
    if ( supportFlash() ) {
        var str = '<object type="application/x-shockwave-flash"></object>';
        return $(str).appendTo($('body'));
    }
    return 'nextSuccessor';
};

var getFormUpladObj = function () {
    return $('<form><input name="file" type="file"/></form>').appendTo($('body'));
};

var getUploadObj = getActiveUploadObj.after(getFlashUploadObj).after(getFormUpladObj);
console.log(getUploadObj());

标签:function,const,前端,责任,handler,params,new,return,设计模式
来源: https://www.cnblogs.com/suanyunyan/p/16434917.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有