KWIC—Implicit Invocation
KWIC—Implicit Invocation
✏️ KWIC—Implicit Invocation
文章目录
- KWIC—Implicit Invocation
- 📝KWIC—Implicit Invocation
- 🧩KWIC
- 🧩核心组件
- 🧩ImplementationScheme
- ⚖️ 隐式调用 vs 显式调用对比
- 🌟 总结
📝KWIC—Implicit Invocation
🧩KWIC
KWIC(Key Word In Context)系统是一个经典的软件架构案例,本实现采用了隐式调用(Implicit Invocation)架构风格。该系统的主要功能是对输入文本进行循环移位并按字母顺序排序输出。
传统的 KWIC 实现通常通过函数调用顺序显式连接模块,例如:输入 → 循环移位 → 排序 → 输出。但这种方式导致模块间耦合度高、可维护性差。
在本系统中,模块间不直接调用,而是通过事件驱动机制进行通信:
- 每当有新输入,
Inputer
会广播InsertToTextLineEvent
CircularShifter
监听此事件,进行移位操作- 移位完成后,广播
InsertToTextLinesEvent
Alphabetizer
接收到该事件后执行排序与输出
这种事件触发机制大大增强了系统的灵活性与扩展性。
模块 | 职责说明 |
---|---|
Inputer | 负责读取文件并逐行生成事件 |
CircularShifter | 监听输入事件,对每一行生成所有移位组合 |
Alphabetizer | 监听移位事件,对所有移位结果按字母序排序 |
Outputer | 接收最终结果,负责控制台打印与文件输出 |
EventManager | 管理监听器注册、注销及事件广播 |
🧩核心组件
- 事件管理器(EventManager):作为系统的中枢,负责协调各组件间的通信
- 维护监听器列表
- 提供监听器注册/注销方法
- 实现事件广播机制
- 输入处理(Inputer):负责读取输入文件
- 逐行读取文本内容
- 触发文本行插入事件
- 循环移位器(CircularShifter):处理文本的循环移位
- 监听文本行插入事件
- 为每行生成所有可能的移位组合
- 触发文本行集合插入事件
- 字母排序器(Alphabetizer):对移位结果进行排序
- 监听移位完成事件
- 对结果进行字母序排序
- 输出最终结果

🧩ImplementationScheme
A third way for styles to
be combined is to
elaborate one level of
package com.wy;
import java.io.IOException;
import java.util.Collections;public class Alphabetizer implements KWICListener{private TextLines textlines=null;@Overridepublic void handleEvent(KWICEvent event) {if(event instanceof InsertToTextLinesEvent){textlines=((CircularShifter) event.getSource()).getTextLines();Collections.sort(textlines.getLineList());try {Outputer.println(textlines);} catch (IOException e) {e.printStackTrace();}}}
}
package com.wy;
import java.util.ArrayList;public class CircularShifter implements KWICListener{private TextLines textlines=null;@Overridepublic void handleEvent(KWICEvent event) {if(event instanceof InsertToTextLineEvent){TextLine textline=((Inputer) event.getSource()).getTextLine();int number_of_lines=textline.numberOfLines();ArrayList<ArrayList> exlist=new ArrayList<ArrayList>(0);ArrayList<String> inlist=new ArrayList<String>(0);for(int i=0;i<number_of_lines;i++){for(int j=0;j<textline.numberOfWords(i);j++){if(j==0) {inlist.add(textline.getLine(i));}else {inlist.add(textline.shiftwords(i));}}exlist.add(inlist);inlist=new ArrayList<String>(0);}textlines=new TextLines();for(int i=0;i<number_of_lines;i++){for(int j=0;j<exlist.get(i).size();j++){textlines.addLine((String)exlist.get(i).get(j));}}InsertToTextLinesEvent ittles=new InsertToTextLinesEvent(this);EventManager.broadcast(ittles);}}public TextLines getTextLines(){return textlines;}
}
package com.wy;
import java.util.ArrayList;
import java.util.List;public class EventManager {// 监听器列表private static List<KWICListener> listenerList = new ArrayList<KWICListener>();// 监听器注册方法public static void addListener(KWICListener listener) {listenerList.add(listener);}// 监听器注销方法public static void removeListener(KWICListener listener) {listenerList.remove(listener);}// 事件广播方法public static void broadcast(KWICEvent event) {for(KWICListener listener : listenerList)listener.handleEvent(event);}
}
package com.wy;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;public class Inputer {private TextLine textline=null;public Inputer(FileReader fr) throws IOException {input(fr);}public void input(FileReader fr) throws IOException{BufferedReader br=new BufferedReader(fr);textline=new TextLine();while(br.ready()){textline.addLine(br.readLine());InsertToTextLineEvent ittle=new InsertToTextLineEvent(this);EventManager.broadcast(ittle);}}public TextLine getTextLine(){return textline;}
}
package com.wy;
public class InsertToTextLineEvent extends KWICEvent{public InsertToTextLineEvent(Object source) {super(source);}
}
package com.wy;public class InsertToTextLinesEvent extends KWICEvent{public InsertToTextLinesEvent(Object source) {super(source);}
}
package com.wy;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;public class KWIC {public static void main(String args[]) throws IOException{EventManager.addListener(new CircularShifter());EventManager.addListener(new Alphabetizer());FileReader fr=new FileReader("D:\\TXJG\\KWICY\\src\\main\\resources\\input.txt");Inputer inputer=new Inputer(fr);}
}
package com.wy;
import java.util.EventObject;public class KWICEvent extends EventObject{public KWICEvent(Object source) {super(source);}
}
package com.wy;
import java.util.EventListener;public interface KWICListener extends EventListener{public void handleEvent(KWICEvent event);
}
package com.wy;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;public class Outputer {public static void println(TextLines textlines) throws IOException {try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {System.out.println("==== 输出开始 ====");for (int i = 0; i < textlines.numberOfLines(); i++) {String line = textlines.getLine(i);bw.write(line);bw.newLine(); // 写入文件System.out.println(line); // 同时打印到控制台}System.out.println("==== 输出完成 ====");}}
}
package com.wy;
import java.util.ArrayList;public class TextLine {private ArrayList<String> lines=null;public TextLine(){lines=new ArrayList<String>();}public String getLine(int index){return lines.get(index);}public ArrayList<String> getLineList(){return lines;}public void addLine(String line){lines.add(line);}public void addLine(int index,String line){lines.add(index,line);}public int numberOfLines(){return lines.size();}public int numberOfWords(int index){return lines.get(index).split(" ").length;}public String shiftwords(int line_index){String line=this.getLine(line_index);int temp_index=line.indexOf(' ');String temp1="";String temp2="";if(temp_index!=-1){temp1=line.substring(0,temp_index);temp2=line.substring(temp_index+1);lines.set(line_index,temp2+" "+temp1);return temp2+" "+temp1;}else return null;}
}
package com.wy;
import java.util.ArrayList;public class TextLines {private ArrayList<String> lines=null;public TextLines(){lines=new ArrayList<String>();}public String getLine(int index){return lines.get(index);}public ArrayList<String> getLineList(){return lines;}public void addLine(String line){lines.add(line);}public void addLine(int index,String line){lines.add(index,line);}public int numberOfLines(){return lines.size();}public int numberOfWords(int index){return lines.get(index).split(" ").length;}
}
⚖️ 隐式调用 vs 显式调用对比
对比项 | 隐式调用(当前实现) | 显式调用(传统调用) |
---|---|---|
耦合度 | 低,模块通过事件通信 | 高,模块之间需直接引用调用 |
可扩展性 | 高,新增功能只需注册监听器 | 低,需修改原始模块 |
调试难度 | 相对较高,需跟踪事件链路 | 低,调用路径明确 |
控制流掌握 | 不明显,控制权分散 | 明确,调用顺序可控 |
适用场景 | GUI、分布式系统、日志系统等异步/解耦需求场景 | 简单流程、数据依赖强的系统 |
🌟 总结
特点 | 说明 |
---|---|
松耦合 | 各组件(如 Inputer 、CircularShifter 、Alphabetizer )不直接依赖彼此,而是通过 EventManager 进行事件通信 |
事件驱动 | 采用观察者模式,KWICListener 监听事件,KWICEvent 触发相应处理逻辑 |
职责分离 | 每个模块专注于单一功能(如输入、移位、排序、输出),符合单一职责原则(SRP) |
可扩展性 | 新增处理逻辑只需注册新监听器,无需修改现有代码 |
KWIC 的隐式调用架构通过事件机制实现模块间通信,相比传统分层或管道-过滤器架构,具有更高的灵活性和可维护性。该设计模式适用于需要动态扩展、松耦合的场景,是事件驱动架构(EDA)的典型实践。
相关文章:

KWIC—Implicit Invocation
KWIC—Implicit Invocation ✏️ KWIC—Implicit Invocation 文章目录 KWIC—Implicit Invocation📝KWIC—Implicit Invocation🧩KWIC🧩核心组件🧩ImplementationScheme⚖️ 隐式调用 vs 显式调用对比 🌟 总结 &#x…...

Visual Studio 2022 发布独立的 exe 文件
我们在用 Visual Studio 2022 写好一个 exe 程序之后,如果想把这个拿到其他地方运行,需要把 exe 所在的文件夹一起拿过去。 编译出来的 exe 文件需要其他几个文件一同放在同一目录才能运行,原因在于默认情况下,Visual Studio 是把…...

11.4java语言执行浅析4
编译成字节码(.class 文件) 使用 javac 命令将源代码编译为 Java 字节码(bytecode) 它不是机器码,而是 JVM 能理解的中间语言(字节码),具有平台无关性。 编译过程简要࿱…...
Excel 操作 转图片,转pdf等
方式一 spire.xls.free(没找设置分辨率的方法) macOs开发Java GUI程序提示缺少字体问题解决 Spire.XLS:一款Excel处理神器_spire.xls免费版和收费版的区别-CSDN博客 官方文档 Spire.XLS for Java 中文教程 <dependency><groupI…...
说说 Kotlin 中的 Any 与 Java 中的 Object 有何异同?
在 Kotlin 中 Any 类型和 Java 中的 Object 类都是所有类型的根类型。 1 基本定义 Kotlin 中的 Any 和 Any?: Any:是所有非空类型的根类型;Any?:是所有可空类型的根类型; Java 中的 Object: 是所有类…...

python分配方案数 2023年信息素养大赛复赛/决赛真题 小学组/初中组 python编程挑战赛 真题详细解析
python分配方案数 2023全国青少年信息素养大赛Python编程挑战赛复赛真题解析 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】1、Python比赛 信息素养大赛Python编程挑战赛 蓝桥杯python选拔赛真题详解...

《信号与系统》第 5 章 离散时间傅里叶变换
5.0 引言 这一章将介绍并研究离散时间傅里叶变换,这样就完整地建立了傅里叶分析方法。 5.1 非周期信号的表示:离散时间傅里叶变换 5.1.1 离散时间傅里叶变换的导出 在第4章看到:一个连续时间周期方波的傅里叶级数可以看成一个包络函数的采…...

动态IP与区块链:重构网络信任的底层革命
在数字经济蓬勃发展的今天,网络安全与数据隐私正面临前所未有的挑战。动态IP技术与区块链的深度融合,正在构建一个去中心化、高可信的网络基础设施,为Web3.0时代的到来奠定基础。 一、技术碰撞:动态IP与区块链的天然契合 动态I…...
目前主流图像分类模型的详细对比分析
以下是目前主流图像分类模型的详细对比分析,结合性能、架构特点及应用场景进行整理: 一、主流模型架构分类与定量对比 模型名称架构类型核心特点ImageNet Top-1准确率参数量(百万)计算效率典型应用场景ResNetCNN残差连接解决梯度…...

uniapp使用Canvas生成电子名片
uniapp使用Canvas生成电子名片 工作中有生成电子名片的一个需求,刚刚好弄了发一下分享分享 文章目录 uniapp使用Canvas生成电子名片前言一、上代码?总结 前言 先看效果 一、上代码? 不对不对应该是上才艺,哈哈哈 <template…...

世冠科技亮相中汽中心科技周MBDE会议,共探汽车研发数字化转型新路径
近日,中汽中心2025年科技周MBDE前沿应用主题会议在天津成功举办。本次会议以“智汇津门共探MBDE前沿应用新征程”为主题,聚焦基于模型的数字工程(MBDE)方法论在汽车复杂系统研发中的创新实践与跨领域协同,旨在推动行业…...

Linux笔记---线程
1. 线程的介绍 1.1 线程的概念 基本定义: 线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程(Process)之中(或者说是进程的一部分、对进程的划分),是进程中的实际…...

MCP架构深度解析:从基础原理到核心设计
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…...
【监控】pushgateway中间服务组件
Pushgateway 是 Prometheus 生态中的一个中间服务组件,以独立工具形式存在,主要用于解决 Prometheus 无法直接获取监控指标的场景,弥补其定时拉取(pull)模式的不足。 其用途如下: 突破网络限制࿱…...

数据库暴露--Get型注入攻击
1.背景知识 1.1Post、Get的对比 特性GET 方法POST 方法HTTP 方法类型GETPOST数据位置URL 查询字符串(?key=value)请求体(Request Body)数据可见性明文显示在 URL 和浏览器历史中不可见(除非开发者工具查看)数据长度限制受 URL 长度限制(通常约 2048 字符)无明确限制(…...

AI炼丹日志-26 - crawl4ai 专为 AI 打造的爬虫爬取库 上手指南
点一下关注吧!!!非常感谢!!持续更新!!! Java篇: MyBatis 更新完毕目前开始更新 Spring,一起深入浅出! 大数据篇 300: Hadoop&…...

ESP32-idf学习(四)esp32C3驱动lcd
一、前言 屏幕是人机交互的重要媒介,而且现在我们产品升级的趋势越来越高大尚,不少产品都会用lcd来做界面,而esp32c3在一些项目上是可以替代主mcu,所以驱动lcd也是必须学会的啦 我新买的这块st7789,突然发现是带触摸…...

【python】uv管理器
uv是一个速度极快的 Python 包和项目管理器,用 Rust 编写。 安装 安装uv之前,确保你的电脑不需要安装了python 在Windows下,可以使用官方的脚本直接安装 powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.…...
关于Web安全:7. WebShell 管理与持久化后门
一、菜刀马 菜刀马(ChinaZ WebShell) 是一种与“中国菜刀(ChinaZ)”客户端配合使用的 WebShell 木马,广泛应用于 Web 渗透测试中,主要使用 PHP/ASP/JSP 等语言编写。 它的本质是一个一句话木马࿰…...
音视频中的复用器
🎬 什么是复用器(Muxer)? 复用器(muxer)是负责把音频、视频、字幕等多个媒体流打包(封装)成一个单一的文件格式的组件。 💡 举个形象的例子: 假设你有两样东…...

戴尔AI服务器订单激增至121亿美元,但传统业务承压
戴尔科技121亿美元的AI服务器订单,不仅超过了公司整个2025财年的AI服务器出货量,更让其AI订单积压达到144亿美元的历史高位。 戴尔科技最新财报显示,AI服务器需求的爆炸式增长正在重塑这家老牌PC制造商的业务格局,但同时也暴露出…...
远程线程注入
注入简单来说就是让别人的程序执行 你想要让他执行的dll #include<iostream> #include<Windows.h> using namespace std;char szBuffer[] "C:\\Users\\20622\\source\\repos\\Dll1\\Debug\\test.dll"; //dll路径void RemoteThreadInject(DWORD Pid,PCH…...

如何手搓扫雷(待扩展)
文章目录 一、扫雷游戏分析与设计1.1 扫雷游戏的功能说明1.2 游戏的分析和设计1.2.1 数据结构的分析1.2.2 文件结构设计 二、扫雷游戏的代码实现三、扫雷游戏的扩展总结 一、扫雷游戏分析与设计 扫雷游戏网页版 1.1 扫雷游戏的功能说明 使用控制台(黑框框的程序&a…...

俄军操作系统 Astra Linux 安装教程
安装 U盘制作 Rufus 写盘工具:https://rufus.ie/ Astra Linux ISO 镜像文件:https://dl.astralinux.ru/astra/stable/2.12_x86-64/iso/ 准备一个8g以上的u盘,打开Rufus写盘工具,选择下载的iso镜像,写入u盘ÿ…...

第三方软件评测机构如何助力软件品质提升及企业发展?
第三方软件评测机构与软件开发者及使用者无直接关联,它们提供全方位的检测和公正的评价服务。这样的评测可以展现客观的成效,对提升软件的品质具有显著影响,且在软件产业中发挥着至关重要的角色。 评测的客观性 独立第三方机构与软件开发者…...

Python打卡训练营Day40
DAY 40 训练和测试的规范写法 知识点回顾: 彩色和灰度图片测试和训练的规范写法:封装在函数中展平操作:除第一个维度batchsize外全部展平dropout操作:训练阶段随机丢弃神经元,测试阶段eval模式关闭dropout 作业&#x…...
【仿生系统】爱丽丝机器人的设想(可行性优先级较高)
非程序化、能够根据环境和交互动态产生情感和思想,并以微妙、高级的方式表达出来的能力 我们不想要一个“假”的智能,一个仅仅通过if-else逻辑或者简单prompt来模拟情感的机器人。您追求的是一种更深层次的、能够学习、成长,并形成独特“个性…...

JS逆向案例—喜马拉雅xm-sign详情页爬取
JS逆向案例——喜马拉雅xm-sign详情页爬取 声明网站流程分析总结 声明 本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权&am…...
钩子函数的作用(register_hook)
钩子函数仅在backward()时才会触发。其中,钩子函数接受梯度作为输入,返回操作后的梯度,操作后的梯度必须要输入的梯度同类型、同形状,否则报错。 主要功能包括: 监控当前的梯度(不返回值)&…...
电子电路:深入了解CMOS技术构造和工作原理
一、CMOS的基本结构与工作原理 1. 核心结构:互补MOSFET CMOS(互补金属氧化物半导体)的核心是成对的NMOS(N沟道MOSFET)和PMOS(P沟道MOSFET)晶体管,两者共享同一硅衬底但通过阱(Well) 隔离: NMOS:构建在P型衬底上,源/漏极为N⁺掺杂区。当栅极电压(V_GS)高于阈值…...