The Chain Of Responsibility 1

                       

今天分享一下,设计模式中的责任链模式,其余的不过多叙述。


思路

在正式接触责任连之前,我们可以想象到的应该是一个链,链表?要处理一件事需要一个链似得?其实答案差不多就是这样。设计模式也都是从朴素的思维中经过一系列的总结得到的。下面来谈一谈责任链的进化之路。

来源

责任链也是从实际的开发中不断升华得到的一个“套路”,这也是称之为“模式”的原因了。比如说,我们现在要对用户上传的数据进行过滤。要实现这样的一个功能,我们首先想到的可能是下面这样的。

// 待处理的用户的输入数据        String message = "<script>while(1){alert('HaHa,敏感词,替换词')</script>";         String result = message.replaceAll("<","[");         result = result.replaceAll(">","]");        System.out.println("未被处理的数据为:" + message);        System.out.println("经过处理的数据为:" + result);
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

很简单了吧,但是想一想,这样真的够了吗?

 

其实String类的设计就是一个链的模式,这点我们可以从replaceAll方法中看出一点端倪。

加大点难度

现在假如说添加了一个更加高级点的功能,那就是实现对HTML的代码的转义,敏感词的过滤,替换词的替换等等。那么如果我们还这样写的话,这个方法体就会变的很大,而且不容易进行维护。而根据面向对象的思维,我们不难想到抽象出一个接口,要想实现哪种功能,就直接让其实现这个接口完成相应的业务逻辑就好了嘛。

下面我们就来看看这种实现。
首先是接口:Filter.java

package ResponsibilityChain;public interface Filter {    public String doFilte(String message);}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

HTMLFilter.java

package ResponsibilityChain;/** * HTML filter utility. *  * 但是也添加了一些修改内容 * * @author Craig R. McClanahan * @author Tim Tye */public final class HTMLFilter implements Filter{    /**     * Filter the specified message string for characters that are sensitive in     * HTML. This avoids potential attacks caused by including JavaScript codes     * in the request URL that is often reported in error messages.     *     * @param message     *            The message string to be filtered     */    public String doFilte(String message) {        if (message == null)            return (null);        char content[] = new char[message.length()];        message.getChars(0, message.length(), content, 0);        StringBuilder result = new StringBuilder(content.length + 50);        for (int i = 0; i < content.length; i++) {            switch (content[i]) {            case '<':                result.append("&lt;");                break;            case '>':                result.append("&gt;");                break;            case '&':                result.append("&amp;");                break;            case '"':                result.append("&quot;");                break;            default:                result.append(content[i]);            }        }        return (result.toString());    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

SesitiveFilter.java

package ResponsibilityChain;public final class SesitiveFilter implements Filter {    @Override    public String doFilte(String message) {        // 正常来说应该是个词库的,对词库中的数据进行匹配,这样比较合理一些,此处为了掩饰核心思想,就简化了这个操作        String str = message.replaceAll("敏感词", "不敏感了");        return str;    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

ReplacableFilter.java

package ResponsibilityChain;public class ReplacableFilter implements Filter {    @Override    public String doFilte(String message) {        // 正常来说应该是个词库的,对词库中的数据进行匹配,这样比较合理一些,此处为了掩饰核心思想,就简化了这个操作        String str = message.replaceAll("替换词", "已被替换");        return str;    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

然后是一个业务逻辑的管家了,它负责接收要进行过滤的数据,并且返回处理过的数据,MyProcessor.java

package ResponsibilityChain;public class MyProcessor {    private String msg;    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public String process() {        // 调用相关的过滤器进行词汇的过滤        HTMLFilter htmlFilter = new HTMLFilter();        String result = htmlFilter.doFilte(msg);        // 调用敏感词过滤器        SesitiveFilter sesitiveFilter = new SesitiveFilter();        result = sesitiveFilter.doFilte(result);        ReplacableFilter replacableFilter = new ReplacableFilter();        result = replacableFilter.doFilte(result);        return result;    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

最后来个测试吧。Main.java

package ResponsibilityChain;public class Main {    public static void main(String[] args) {        // 待处理的用户的输入数据        String message = "<script>while(1){alert('HaHa,敏感词,替换词')</script>";         MyProcessor myProcessor = new MyProcessor();         myProcessor.setMsg(message);         String result = myProcessor.process();        System.out.println("未被处理的数据为:" + message);        System.out.println("经过处理的数据为:" + result);    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
 

小总结
   这样就可以实现我们需要的功能了,我们可以在MyProcessor类中添加我们的过滤器,完成所有我们需要的功能。但是看一下,

public String process() {        // 调用相关的过滤器进行词汇的过滤        HTMLFilter htmlFilter = new HTMLFilter();        String result = htmlFilter.doFilte(msg);        // 调用敏感词过滤器        SesitiveFilter sesitiveFilter = new SesitiveFilter();        result = sesitiveFilter.doFilte(result);        ReplacableFilter replacableFilter = new ReplacableFilter();        result = replacableFilter.doFilte(result);        return result;    }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这段代码,总是感觉有点冗余,给人的感觉就是有点笨重了。下面我们就来解决一下这个问题。

责任链前身

为了解决上面的代码过于冗余,下面引入了责任链的前身,那就是使用一个数组保存我们所有的Filter的实现类,用于管理我们的过滤任务。我们只需要在MyProcessor类中进行修改即可。
如下,MyProcessor2.java

package ResponsibilityChain;public class MyProcessor2 {    Filter[] filters = { new HTMLFilter(), new SesitiveFilter(), new ReplacableFilter() };    private String msg;    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public String process() {        String result = msg;        for (Filter f : filters) {            result = f.doFilte(result);        }        return result;    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

测试一下:

package ResponsibilityChain;public class Main2 {    public static void main(String[] args) {        // 待处理的用户的输入数据        String message = "<script>while(1){alert('HaHa,敏感词,替换词')</script>";        MyProcessor2 myProcessor2 = new MyProcessor2();        myProcessor2.setMsg(message);        String result = myProcessor2.process();        System.out.println("未被处理的数据为:" + message);        System.out.println("经过处理的数据为:" + result);    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
 

小总结:这里我们明显的可以看到使用了数组来进行管理的好处了吧,我们只需要在添加新的过滤器实现类的时候在这个数组里面就可以了。
  这样看着,有点意思了吧。

责任链出山

看完了上面的代码,想必对这个业务逻辑很熟悉了吧。但是这还不是我们的责任链模式,没有体现出“链”的特点,而且假如说我们有两个这样的数组,要合作的完成过滤任务,而且是在一个完成一半的时候插入另一个数组的任务,这样的话,就比较的棘手了吧。所以下面要交给责任链来进行管理了。
FilterChain.java

package ResponsibilityChain;import java.util.ArrayList;import java.util.List;public class FilterChain implements Filter{    private List<Filter> filters = new ArrayList<Filter>();    /**     * return itself for better usage the Chain     *      * @param f     * @return     */    public FilterChain addFilter(Filter f) {        filters.add(f);        return this;    }    public void remove(Filter f) {        filters.remove(f);    }    /**     * For the chain , it's also a chain for filter     *      * @param message     *            message need to be filtered     * @return     */    public String doFilte(String message) {        String result = message;        for (Filter f : filters) {            result = f.doFilte(result);        }        return result;    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

这样一来,MyProcessor也要进行修改,如MyProcessor3.java

package ResponsibilityChain;public class MyProcessor3 {    private FilterChain filterChain;    public FilterChain getFilterChain() {        return filterChain;    }    public void setFilterChain(FilterChain filterChain) {        this.filterChain = filterChain;    }    private String msg;    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    // 此处为核心and关键    public String process() {        String result = msg;        result = filterChain.doFilte(result);        return result;    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

再来测试一把,Main3.java

package ResponsibilityChain;public class Main3 {    public static void main(String[] args) {        // 待处理的用户的输入数据        String message = "<script>while(1){alert('HaHa,敏感词,替换词')</script>";        MyProcessor3 myProcessor3 = new MyProcessor3();        myProcessor3.setMsg(message);        FilterChain filterChain = new FilterChain();        // filterChain.addFilter(new HTMLFilter());        // filterChain.addFilter(new SesitiveFilter());        // filterChain.addFilter(new ReplacableFilter());        myProcessor3.setFilterChain(filterChain);        // 作为一个链的方式进行添加过滤器,这就是链式编程的好处        filterChain.addFilter(new HTMLFilter()).addFilter(new SesitiveFilter()).addFilter(new ReplacableFilter());        String result = filterChain.doFilte(message);           System.out.println("未被处理的数据为:" + message);        System.out.println("经过处理的数据为:" + result);    }}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

这里就需要好好的来个总结了,经典的思想总是让人感叹啊。
不知道你有没有注意到在FilterChain.java中

public FilterChain addFilter(Filter f) {        filters.add(f);        return this;    }
  
  • 1
  • 2
  • 3
  • 4

这个方法就可以完成“链”的效果。返回自身,这样就可以不断的调用同样的方法,链式的完成任务。
还有FilterChain也有一个doFilte的方法,也就是说我们将完成过滤的功能从MyProcessor.java类中迁移到了FilterChain类中了。

而且实现了Filter接口的FilterChain也就可以完成添加更加自由的过滤规则了。

 

这就是面向对象的核心,一个对象能完成什么功能完全取决于其自身的属性。

这样我们在MyProcessor3.java中只需要调用责任链的这个过滤功能就可以了。

总结

本文从一个现实中的问题出发,从简单的朴素的思想,一步步的经过面向对象的强化以及经典的责任链思想的牵引。完成了一个简单的责任链模式的小例子。

如果细心的品味一下,肯定会有不少感触的吧。责任链模式在实际的开发过程中也是很常见的,比如说Struts2的拦截器栈等等。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值