管道模式 流处理

news2024/9/21 11:14:54

(一)介绍

管道这个名字源于自来水厂的原水处理过程。原水要经过管道,一层层地过滤、沉淀、去杂质、消毒,到管道另一端形成纯净水。我们不应该把所有原水的过滤都放在一个管道中去提纯,而应该把处理过程进行划分,把不同的处理分配在不同的阀门上,第一道阀门调节什么,第二道调节什么……最后组合起来形成过滤纯净水的管道。
这种处理方式实际上体现了一种分治(Divid and Conquer)思想,这是一种古老且非常有效的思想。接下来,我们来看管道模式的实际应用。

(二)链式管道

一个典型的管道模式,会涉及以下3个主要的角色。
(1)阀门:处理数据的节点。(2)管道:组织各个阀门。(3)客户端:构造管道并调用。
对应现实生活中的管道,我们一般使用一个单向链表数据结构作为来实现,如图所示。这也是链式管道区别于拦截器模式之处。其实在功能上,拦截器、管道、过滤器、责任链有类似之处,在实际工作中,我们可以根据具体情况灵活选用。
在这里插入图片描述
在这里插入图片描述
为了便于理解,我找了一个管道阀门的图,结合上图可以更加容易理解。

【1】管道和阀门的整体结构就类似于一个链表结构,其中阀门是链表中的节点
【2】管道中可以添加和删除阀门,阀门按照顺序依次进行处理
【3】阀门可以根据需要对管道输入进行过滤处理。

基于上面的分析,我们可以按照下面的步骤实现一个简单的链式管道。

(1)阀门接口

/**
 * 阀门接口
 *
 * @author zhangyu
 * @date 2022/12/4
 **/
public interface Valve {

    /**
     * 获取下一个阀门节点
     */
    Valve getNext();

    /**
     * 设置下一个阀门节点
     */
    void setNext(Valve v);

    /**
     * 当前阀门处理逻辑
     */
    void invoke(String s);

}

(2)管道接口:

/**
 * 管道接口
 *
 * @author zhangyu
 * @date 2022/12/4
 **/
public interface Pipeline {

    /**
     * 获取管道中的第一个阀门节点
     */
    public Valve getHead();

    /**
     * 获取管道中的第一个尾部阀门节点
     */
    public Valve getTail();

    /**
     * 设置管道中的第一个尾部阀门节点
     */
    public void setTail(Valve v);

    /**
     * 为管道添加阀门节点
     */
    public void addValve(Valve v);
}

2.创建阀门的基础实现

/**
 * 阀门的基础实现
 *
 * @author zhangyu
 * @date 2022/12/4
 **/
public abstract class ValveBase implements Valve {
    public Valve next;

    public Valve getNext() {
        return next;
    }

    public void setNext(Valve v) {
        next = v;
    }

    public abstract void invoke(String s);
}

3.实现具体的阀门
普通阀门一:当前模拟实现的场景是将输入字符串中的11替换为first字符串

public class FirstValve extends ValveBase {

    public void invoke(String s) {
        s = s.replace("11", "first");
        System.out.println("FirstValve阀门处理后结果" + s);
        getNext().invoke(s);
    }
}

(2)普通阀门二::当前模拟实现的场景是将输入字符串中的22替换为second字符串

public class SecondValve extends ValveBase {
    @Override
    public void invoke(String s) {
        s = s.replace("22", "second");
        System.out.println("SecondValve阀门处理后结果" + s);
        getNext().invoke(s);
    }
}

(3)尾阀门:

public class TailValve extends ValveBase {
    public void invoke(String s) {
        s = s.replace("33", "third");
        System.out.println("TailValve阀门处理后结果" + s);
    }
}

4.实现具体的管道

public class StandardPipeline implements Pipeline {
    protected Valve head;
    protected Valve tail;

    public Valve getHead() {
        return head;
    }

    public Valve getTail() {
        return tail;
    }

    public void setTail(Valve v) {
        tail = v;
    }

    /**
     * 往链表依次添加节点
     */
    public void addValve(Valve v) {
        if (head == null) {
            // 如果链表为空则当前节点为头结点
            head = v;
            v.setNext(tail);
        } else {
            // 将当前节点添加依次添加到队列
            Valve current = head;
            while (current != null) {
                // 当前节点放入队列尾部,但是需要在tail尾结点前面
                if (current.getNext() == tail) {
                    current.setNext(v);
                    v.setNext(tail);
                    break;
                }
                current = current.getNext();
            }
        }
    }
}

5.组装管道,实现客户端调用

public class Client {
    public static void main(String[] args) {
        String s = "11,22,33";
        System.out.println("原始输入 : " + s);
        StandardPipeline pipeline = new StandardPipeline();
        TailValve tail = new TailValve();
        FirstValve first = new FirstValve();
        SecondValve second = new SecondValve();
        // 设置管道尾部节点
        pipeline.setTail(tail);
        // 依次将节点加入至管道链表中
        pipeline.addValve(first);
        pipeline.addValve(second);
        // 从管道头部开始处理
        pipeline.getHead().invoke(s);
    }
}

6.执行客户端程序并输出结果
在这里插入图片描述

【完整代码】
Github代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytorch Bert 中文分类 运行代码时候遇到的问题

问题1 bert AutoModel.from_pretrained(bert-base-chinese) 报错信息如下: RuntimeError: Error(s) in loading state_dict for BertModel: size mismatch for bert.embeddings.word_embeddings.weight: copying a param with shape torch.Size([21128, 768…

m基于GA遗传算法的PMSM永磁同步电机参数最优计算matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 永磁同步电机(PMSM)基本结构为定子、转子和端盖。其中转子磁路结构是永磁同步电机与其它电机最主要的区别,其在很大程度上决定了永磁同步电机的实际性能指标。…

AtCoder Beginner Contest 280 老年人复建赛

好久没更新了&#xff0c;因为最近p事实在是有点多&#xff0c;让人心烦意乱 还是安安心心打比赛舒服 A&#xff0c;B&#xff0c;C就不讲啦 D - Factorial and Multiple 大意&#xff1a; 给定一个数字k<1e12&#xff0c;求最小的数字n满足n!%k0; 思路1&#xff1a; 不…

hadoop完全分布式环境搭建详细版

1. hadoop集群规划 1.准备3台客户机(关闭防火墙&#xff0c;静态ip&#xff0c;主机名称) 2.安装jdk 3.配置环境变量 4.安装hadoop&#xff0c;hadoop版本是3.1.3,包名为hadoop-3.1.3.tar.gz 5.配置环境变量 6.配置集群 7.单点启动 8.配置ssh 9.群起集群并测试集群 注意: NameN…

Ubuntu20.04静态路由表连通局域网各网段主机 Vmware WorkStation

文章目录示例拓扑虚拟机的三种网络模式虚拟网络编辑器的设置虚拟主机与虚拟路由设置细节Ubuntu20.04设置静态IP给R1添加双网卡给R1、R2开启转发功能配置路由表References示例拓扑 宿主机是Windows11 PC与Router均为 Ubuntu20.04系统。 虚拟机的三种网络模式 虚拟机默认是只初…

如何利用InVest模型估算区域产水量

1.什么是InVEST模型 InVEST模型&#xff08;Integrated Valuation of Ecosystem Services and Tradeoffs &#xff09;是生态系统服务评估与权衡模型的简称&#xff0c;是美国自然资本项目组开发的、用于评估生态系统服务功能量及其经济价值、支持生态系统管理和决策的一套模型…

十四、使用 Vue Router 开发单页应用(1)

本章概要 感受前端路由 HTML 使用路由模块开发使用路由 传统的 Web 应用程序不同页面间的跳转都是向服务器发起请求&#xff0c;服务器处理请求后向浏览器推送页面。 在单页应用程序中&#xff0c;不同视图&#xff08;组件的模板&#xff09;的内容都是在同一个页面中渲染&…

golang 琐碎知识

golang 琐碎知识&#xff08;持续进行&#xff09; 时间格式 time.now.Format("2006-01-02T 15:04:05")make声明切片bug Golang&#xff1a;statusList : make([]*model.StatusList, 6) 会声明一个长为6的null切片&#xff0c;使用append添加时不会将null覆盖掉去掉切…

JMeter入门教程(10) --函数助手

文章目录1.CSVRead2.Random3.RandomString4.RandomDate5.time在JMeter的选项菜单中有一个“函数助手对话框”&#xff0c;点击打开“函数助手”对话框&#xff0c;使用函数助手&#xff0c;我们可以从“选择一个功能”下拉列表中选择一个函数&#xff0c;并为其参数设定值。表格…

SQL函数之分割

数据库中有一张地区数据统计表,但是并不规则 ,记录类似于,225100:02:3:20160725是一串代码,以:分割,第1位为地区代码,第2位为分类代码,第3位为数量,第4位为日期 地区代码含义225100-上海 225200-江苏 225300-浙江 为可能有某些位不存在,缺位时计算规则如下: 1、…

Golang开发习惯:变量、常量声明使用惯例

《Go语言精进之路》第二、三章部分内容学习记录笔记。 1.基本原则 Golang开发中&#xff0c;可遵守简单且一致的命名原则&#xff0c;力求命名精简、易懂和一致。 package声明 Golang的package声明以小写形式的单个词进行命名&#xff1a; shopservice、utils、logs、tcc、l…

计算机毕业论文java毕业设计选题源代码

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 《【论文】S2SH药膳馆会员管理系统》该项目采用技术jsp、strust2、Spring、hibernate、tomcat服务器、mysql数据库 &#xff0c;项目含有源码、论…

十四、使用 Vue Router 开发单页应用(2)

本章概要 动态路由匹配 查询参数 路由匹配语法 参数的自定义正则表达式可重复参数可选参数 嵌套路由 14.2 动态路由匹配 实际项目开发时&#xff0c;经常需要把匹配某种模式的路由映射到同一个组件。例如&#xff0c;有一个 Book 组件&#xff0c;对于所有 ID 各不相同的图书…

MOOC 大数据Note

MOOC 大数据NoteSparkSpark 一个软件栈满足不同交互场景Lineage 血缘关系创建 转换 动作ShuffleMapStageSpark的部署和应用方式RDD操作分为转换&#xff08;Transformation&#xff09;和动作&#xff08;Action&#xff09;两种类型&#xff0c;下列属于动作&#xff08;Actio…

开发工具——gcc/g++

开发工具gcc/g 完成代码的编写完后&#xff0c;要形成可执行程序&#xff0c;需要编译工具进行对代码的编译。 C语言的编译工具是gcc&#xff0c;c的编译工具是g。 如果g没有的话&#xff0c;可以切换到root执行命令yum install -y gcc-c C语言和C的编译&#xff1a; gc…

「点燃我,温暖你」用Python制作一个动态爱心效果

最近「点燃我&#xff0c;温暖你」这部剧非常火&#xff0c;讲述的是程序员的爱情故事。 其中陈飞宇饰演的男主李峋&#xff0c;在剧中用程序做出的爱心跳动效果&#xff0c;非常炫。 网上各个大佬也是纷纷给出看法&#xff0c;综合就是不太可能用C语言来实现的。 大概率是AE…

Reg注册表读写

在Windows 95及其后继版本中&#xff0c;采用了一种叫做“注册表”的数据库来统一进行管理&#xff0c;将各种信息资源集中起来并存储各种配置信息。按照这一原则&#xff0c;Windows各版本中都采用了将应用程序和计算机系统全部配置信息容纳在一起的注册表&#xff0c;用来管理…

Java内存溢出故障案例及Linux内存机制探究

文章目录Java内存溢出故障案例及Linux内存机制探究OOM Killer触发机制分析如何避免系统触发OOM Killer这部分内容属于demo案例分享&#xff0c;解决线上运维问题&#xff0c;思路是最重要的 Java内存溢出故障案例及Linux内存机制探究 这是一个线上数据分析应用故障案例&#…

Java—反射

文章目录什么是反射反射定义java创建对象的三个阶段反射过程反射第一步&#xff1a;获取类对象获取类对象的三种方式反射第二步&#xff1a;获取类信息如何获取类信息&#xff1f;1、获取成员变量&#xff1a;2、获取方法&#xff1a;3、获取构造器反射第三步&#xff1a;使用反…

vue学习笔记——简单入门总结(四)

文章目录1.Vue3的特性和变化1.1.创建vue3项目1.2.分析main.js变化&#xff1a;1.3.setup--组合式api的开端1.4.ref函数和reactive函数&#xff1a;1.5.watch监视属性1.5.watchEffect函数1.6.vue3生命周期&#xff1a;1.Vue3的特性和变化 1.1.创建vue3项目 1.这里我们使用脚手架…