一些工厂实例

我时不时地发现自己摸索了一些旧的代码,以找到示例“我在哪里做过工厂一样的事情”。

上周再次发生这种情况时,我决定只查找所有示例,并创建一个示例项目和有关它的博客文章。

所以在这篇文章中,我:

  • 从简单的“原始” Java SE工厂示例开始
  • 然后使用Java SE SPI
  • Java SE上的CDI
  • Java EE上的 CDI
  • Java EE上的EJB
  • Java SE上的动态SPI
  • 最后是Java EE上的SPI

这个例子

这个示例应用程序是一个非常简单的“ Hello World”,您可以输入名称,并且有多种表达问候的方法。

Greeting Service获取Greeting Factory的实例。 然后,它可以按名称要求工厂提供Greeting (接口),然后工厂将返回正确的实现。

有3种具体的实现方式:

  • English将打招呼“好日子名字”
  • Afrikaans将打招呼“ Goeie dag name” 。 (请参阅https://www.youtube.com/watch?v=CtxB4sbV0pA )
  • Bugs Bunny会打招呼“ Eeee, 什么名字 ?” (请参阅https://www.youtube.com/watch?v=UeVtZjGII-I )

Github中提供了此博客的所有源代码 :

git clone https://github.com/phillip-kruger/factories-example

问候界面:

public interface Greeting {public String getName();public String sayHello(String to);}

香草

这个基本的Java SE应用程序有一个主要方法,该方法可让您传递名称和希望打招呼的方式。

工厂是获得正确实现的基本if-statement

public Greeting getGreeting(String name){if(name.equalsIgnoreCase("BugsBunny")){return new BugsBunny();}else if(name.equalsIgnoreCase("Afrikaans")){return new Afrikaans();}else {return new English();}}

一个具体的实现示例, 英语 :

public class English implements Greeting {@Overridepublic String sayHello(String to) {return "Good day " + to + ".";}@Overridepublic String getName() {return "English";}}

运行示例:

vanilla文件夹中:

mvn clean install

这将构建项目并运行该应用程序。 日志将输出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外运行此命令:

java -jar target/vanilla-1.0.0-SNAPSHOT.jar World BugsBunnySEVERE: Eeee, what's up World ?

另见

  • https://alvinalexander.com/java/java-factory-pattern-example

服务提供商接口(SPI)

上面的示例意味着我可以非常轻松地添加另一个实现,并在询问时更新if statement以返回该实现。

但是,我们要改进的是if-statement 。 我们希望可以在不修改现有代码的情况下添加新的实现。 我要做的就是添加新的实现。

SPI是Java SE的一部分,是允许您构建可插入扩展的API。

将应用程序分解为模块。

我们要做的第一件事是将应用程序分解为模块 :

  • API –这将包含Greeting接口(我们的合同)
  • 引擎–其中将包含服务和工厂(以及默认的英语实现)
  • 其他实现–所有其他实现都变成了自己的模块(因此,一种用于南非荷兰语,另一种用于Bugs Bunny等)

这已经意味着我可以通过创建一个新模块来添加新的实现,而不必触摸代码,只需更新依赖项即可:

<dependencies><dependency><groupId>${project.groupId}</groupId><artifactId>spi-api</artifactId><version>${project.version}</version></dependency><dependency><groupId>${project.groupId}</groupId><artifactId>spi-impl-afrikaans</artifactId><version>${project.version}</version></dependency><dependency><groupId>${project.groupId}</groupId><artifactId>spi-impl-bugsbunny</artifactId><version>${project.version}</version></dependency></dependencies>

映射文件

具体的实现需要通过在/src/main/resources/META-INF/services/添加一个文件com.github.phillipkruger.factory.api.Greeting (接口的全限定名),将其Greeting类注册为实现。 )

文件的内容是实现的名称,例如Bugs Bunny :

com.github.phillipkruger.factory.impl.BugsBunny

该工厂

工厂现在需要获取所有Greetings实例:

ServiceLoader<Greeting> loader = ServiceLoader.load(Greeting.class);Iterator<Greeting> greetingIterator = loader.iterator();while (greetingIterator.hasNext()) {Greeting greeting = greetingIterator.next();loadedGreetings.put(greeting.getName(), greeting);}

现在我们摆脱了工厂中的if-statement

运行示例:

spi文件夹中:

mvn clean install

这将构建项目并运行该应用程序。 日志将输出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外运行此命令:

java -jar spi-engine/target/spi-engine-1.0.0-SNAPSHOT-jar-with-dependencies.jar Johny AfrikaansSEVERE: Goeie dag Johny.

另见

  • https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html

上下文和依赖注入(CDI)

最新版本的CDI允许您在Java SE中使用CDI。 为了创建工厂,我们将创建自己的注释作为称为GreetingProvider的API的一部分:

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface GreetingProvider {String value();}

value是实现的名称。

以上的文字实现 :

@AllArgsConstructorpublic class GreetingProviderLiteral extends AnnotationLiteral<GreetingProvider> implements GreetingProvider {private final String name;@Overridepublic String value() {return this.name;}}

这将允许我们使用@GreetingProvider注释任何具体的实现(现在是RequestScoped CDI Bean),例如英语:

@GreetingProvider("English")@RequestScopedpublic class English implements Greeting {@Overridepublic String sayHello(String to) {return "Good day " + to + ".";}@Overridepublic String getName() {return "English";}}

工厂更改以查找所有@GreetingProvider类:

public class GreetingFactory {@Inject @Anyprivate Instance<Greeting> greetings;public Greeting getGreeting(String name) {Instance<Greeting> instance = greetings.select(new GreetingProviderLiteral(name));if(!instance.isUnsatisfied()){Greeting provider = instance.get();return provider;}else{return new English();}}}

因此,现在我们不再需要SPI映射文件,工厂中没有if-statement ,但是我们仍然必须更新依赖项以包含所需的所有实现。

运行示例:

cdi文件夹中:

mvn clean install

这将构建项目并运行该应用程序。 日志将输出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外运行此命令:

java -jar cdi-engine/target/cdi-engine-1.0.0-SNAPSHOT-jar-with-dependencies.jar Charmaine BugsBunnySEVERE: Eeee, what's up Charmaine ?

另见

  • http://www.mastertheboss.com/jboss-frameworks/cdi/building-a-cdi-2-standalone-java-application
  • http://www.adam-bien.com/roller/abien/entry/injecting_classes_in_java_se

Java EE上的CDI

我们还可以使用CDI在Application Server上创建解决方案。 现在,我们将入口点设为REST服务(而不是主要方法),因此我们需要创建并添加ApplicationConfig来启用JAX-RS:

@ApplicationPath("/api")public class ApplicationConfig extends Application {}

GreetingService现在成为REST资源,使您可以执行GET ,将名称作为PathParam传递,以及将可选方式作为QueryParam进行问候:

@Path("/")@Produces(MediaType.APPLICATION_JSON)public class GreetingService {@Injectprivate GreetingFactory factory;@GET@Path("{to}")public String sayHello(@PathParam("to") String to, @QueryParam("way") List<String> way){//....}}

工厂和带注释的RequestScoped CDI Bean实现与Java SE示例上的CDI完全相同。

运行示例:

该示例可以在3个不同的应用程序服务器上运行(为诚实起见)

  • 野蜂群
  • 开放自由
  • Payara Micro

(您不必下载,安装或配置任何东西,Maven构建会做到这一点)

javaee-cdi文件夹中:

mvn clean install -P wildfly

要么

mvn clean install -P liberty

要么

mvn clean install -P payara

在所有3种情况下,maven都会:

  • 在部署了应用程序的情况下启动应用程序服务器
  • 击中2个REST网址:
    • http:// localhost:8080 / javaee-cdi-engine / api (此列表所有实现)
  • 关闭应用程序服务器(Payara除外)

因此,在日志中,您将看到(类似):

===============================================
["BugsBunny","Afrikaans","English"]
==============================================================================================
["Eeee, what's up Phillip ?","Goeie dag Phillip.","Good day Phillip."]
===============================================

如果运行Payara,则服务器不会关闭,因此您也可以手动测试工厂:

wget -qO- http://localhost:8080/javaee-cdi-engine/api/Donald?way=BugsBunny["Eeee, what's up Donald ?"]

Java EE上的EJB

只是为了完成示例,这是在Java EE上使用EJB的方法(因此没有CDI –因此也没有自定义注释)

我们仅使用JNDI查找命名的EJB。

GreetingService与Java EE CDI示例相同,因此我们仍然有一个REST入口点。 现在,具体的实现变为EJB,例如英语:

@Stateless@EJB(beanInterface = Greeting.class, beanName = "English", name = "English")public class English implements Greeting {@Overridepublic String sayHello(String to) {return "Good day " + to + ".";}@Overridepublic String getName() {return "English";}}

现在, 工厂将基于bean名称进行JNDI查找:

@Log@Statelesspublic class GreetingFactory {@EJB(lookup = "java:module/English")private Greeting english; // defaultpublic Greeting getGreeting(String name) {Greeting g = lookup("java:module/" + name);if(g==null)return english;return g;}public List<Greeting> getAll(){List<Greeting> greetings = new ArrayList<>();try {InitialContext context = new InitialContext();NamingEnumeration<Binding> list = (NamingEnumeration<Binding>)context.listBindings("java:global/javaee-ejb-engine");    while (list.hasMore()) {Binding next = list.next();if(next.getName().endsWith(Greeting.class.getName())){Greeting g = lookup("java:global/javaee-ejb-engine/" + next.getName());if(g!=null && !greetings.contains(g))greetings.add(g);}}} catch (NamingException e) {throw new RuntimeException(e);} return greetings;}private Greeting lookup(String jndi){try {InitialContext context = new InitialContext();Object o = context.lookup(jndi);return (Greeting)o;} catch (NamingException e) {log.log(Level.SEVERE, "Could not lookup [{0}]", jndi);return null;}   }}

运行示例:

与Java EE CDI示例类似,它在Wildfly Swarm , Open Liberty和Payara Micro上运行

javaee-ejb文件夹中:

mvn clean install -P wildfly

(或-P自由或-P payara)

在所有3种情况下,maven都会:

  • 在部署了应用程序的情况下启动应用程序服务器
  • 击中2个REST网址:
    • http:// localhost:8080 / javaee-ejb-engine / api (此列表列出了所有实现)
  • 关闭应用程序服务器(Payara除外)

因此,在日志中,您将看到(类似):

===============================================
["BugsBunny","Afrikaans","English"]
==============================================================================================
["Eeee, what's up Phillip ?","Goeie dag Phillip.","Good day Phillip."]
===============================================

如果运行Payara,则服务器不会关闭,因此您也可以手动测试工厂:

wget -qO- http://localhost:8080/javaee-ejb-engine/api/Barney?way=Afrikaans["Goeie dag Barney."]

动态SPI

到目前为止,添加新实现时,我们唯一要做的就是创建包含Greeting实现的模块,并更新pom.xml以包含新的依赖项。

接下来,让我们看看如何动态加载新的实现(因此无需更新依赖项)。

实现完全类似于Java SE SPI示例,包括映射文件,但是现在我们可以删除模块作为pom.xml依赖项:

<dependencies><dependency><groupId>${project.groupId}</groupId><artifactId>dynamic-spi-api</artifactId><version>${project.version}</version></dependency><!-- This will be loaded dynamically<dependency><groupId>${project.groupId}</groupId><artifactId>dynamic-spi-impl-afrikaans</artifactId><version>${project.version}</version></dependency><dependency><groupId>${project.groupId}</groupId><artifactId>dynamic-spi-impl-bugsbunny</artifactId><version>${project.version}</version></dependency>--></dependencies>

工厂看起来像这样:

public class GreetingFactory {private final Map<String,Greeting> loadedGreetings = new HashMap<>();public GreetingFactory(){URLClassLoader classloader = getURLClassLoader();ServiceLoader<Greeting> loader = ServiceLoader.load(Greeting.class, classloader);Iterator<Greeting> greetingIterator = loader.iterator();while (greetingIterator.hasNext()) {Greeting greeting = greetingIterator.next();loadedGreetings.put(greeting.getName(), greeting);}}public Greeting getGreeting(String name){if(loadedGreetings.containsKey(name)){return loadedGreetings.get(name);}else {return new English();}}private URLClassLoader getURLClassLoader(){File[] pluginFiles = getPluginFiles();ArrayList<URL> urls = new ArrayList<>();for(File plugin:pluginFiles){try{URL pluginURL = plugin.toURI().toURL();urls.add(pluginURL);}catch(MalformedURLException m){log.log(Level.SEVERE, "Could not load [{0}], ignoring", plugin.getName());}}return new URLClassLoader(urls.toArray(new URL[]{}),GreetingFactory.class.getClassLoader());}private File[] getPluginFiles(){File loc = new File("plugins");File[] pluginFiles = loc.listFiles((File file) -> file.getPath().toLowerCase().endsWith(".jar"));return pluginFiles;}}

基本上,工厂仍将使用SPI的ServiceLoader加载可用的问候语,但我们传入自定义的ClassLoader。我们在plugins文件夹中查找任何jar文件,并使用URLClassloader加载。

这意味着我现在可以只创建一个新的实现模块并将文件放在plugins文件夹中。 美观且可插拔。

运行示例:

dynamic-spi文件夹中:

mvn clean install

这将构建项目并运行该应用程序。 日志将输出:

SEVERE: Good day Phillip.Goeie dag Phillip.Eeee, what's up Phillip ?

您也可以在Maven之外运行此命令:

java -jar dynamic-spi-engine/target/dynamic-spi-engine-1.0.0-SNAPSHOT-jar-with-dependencies.jar Madonna BugsBunnySEVERE: Eeee, what's up Madonna ?

Java EE上的动态SPI

现在,这是否是个好主意,将进行另外的讨论,只是为了表明它是可能的,我们现在将使用动态SPI在应用程序服务器上加载实现。 这意味着我可以向正在运行的服务器添加新的实现。 因此,我不仅可以在不接触代码或依赖项的情况下添加新的实现,而且还可以启用该新实现而无需重新启动应用程序。

实现看起来完全像Java SE SPI示例, pom.xml不包含任何实现模块,并且我们现在有了一个新类,可以将模块加载到plugins文件夹中:

这是一个ApplicationScoped CDI Bean,可在启动时加载模块。 这些模块也可以通过REST重新加载:

@Path("/pluginloader")@ApplicationScoped@Logpublic class PluginLoader {@Produces @Named("Greetings")private final Map<String,Greeting> loadedGreetings = new HashMap<>();public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {loadPlugins();}@GET@Path("/reload")public Response loadPlugins(){ClassLoader classloader = getClassLoader();ServiceLoader<Greeting> loader = ServiceLoader.load(Greeting.class, classloader);Iterator<Greeting> greetingIterator = loader.iterator();while (greetingIterator.hasNext()) {Greeting greeting = greetingIterator.next();log.log(Level.SEVERE, "Adding provider [{0}]", greeting.getName());if(!loadedGreetings.containsKey(greeting.getName())){loadedGreetings.put(greeting.getName(), greeting);}}return Response.ok("ok").build();}private ClassLoader getClassLoader(){File[] pluginFiles = getPluginFiles();if(pluginFiles!=null){        ArrayList<URL> urls = new ArrayList<>();for(File plugin:pluginFiles){try{URL pluginURL = plugin.toURI().toURL();urls.add(pluginURL);}catch(MalformedURLException m){log.log(Level.SEVERE, "Could not load [{0}], ignoring", plugin.getName());}}return new URLClassLoader(urls.toArray(new URL[]{}),this.getClass().getClassLoader());}return this.getClass().getClassLoader();}private File[] getPluginFiles(){File loc = getPluginDirectory();if(loc==null)return null;File[] pluginFiles = loc.listFiles((File file) -> file.getPath().toLowerCase().endsWith(".jar"));return pluginFiles;}private File getPluginDirectory(){File plugins = new File("plugins");if(plugins.exists())return plugins;  return null;}}

所有加载的GreetingsMap<String,Greeting>中都可用,可以将其注入工厂 :

@RequestScoped@Logpublic class GreetingFactory {@Inject @Named("Greetings")private Map<String,Greeting> greetings;// ...}

运行示例:

与Java EE CDI和EJB示例类似,它在Wildfly Swarm , Open Liberty和Payara Micro上运行

javaee-spi文件夹中:

mvn clean install -P wildfly

(或-P自由或-P payara)

在所有3种情况下,maven都会:

  • 在部署了应用程序的情况下启动应用程序服务器
  • 击中2个REST网址:
    • http:// localhost:8080 / javaee-spi-engine / api (此列表列出了所有实现)
  • 关闭应用程序服务器(Payara除外)

因此,在日志中,您将看到(类似):

===============================================
["BugsBunny","Afrikaans","English"]
==============================================================================================
["Eeee, what's up Phillip ?","Goeie dag Phillip.","Good day Phillip."]
===============================================

如果运行Payara,则服务器不会关闭,因此您也可以手动测试工厂:

wget -qO- http://localhost:8080/javaee-spi-engine/api/Frans?way=Afrikaans["Goeie dag Frans."]

当前,在plugins文件夹中,您将看到2个已知的实现(南非荷兰语和Bugs Bunny):

ls javaee-spi-engine/plugins/javaee-spi-impl-afrikaans-1.0.0-SNAPSHOT.jar  javaee-spi-impl-bugsbunny-1.0.0-SNAPSHOT.jar

当我们构建这些实现时,将其复制到那里。

现在,让服务器保持运行状态,并添加一种新的问候方式,称为AliG。 (请参阅https://www.youtube.com/watch?v=b00lc92lExw )

cd javaee-spi-impl-aligmvn clean install -P plugin

这会将Ali G实现复制到plugins文件夹。

现在,让我们再次问候Frans:

wget -qO- http://localhost:8080/javaee-spi-engine/api/Frans?way=AliG["Booyakasha Frans !"]

因此,我们可以向正在运行的服务器添加新的具体实现。

结束

就是这样(现在)。 欢迎任何评论和您自己的示例!

翻译自: https://www.javacodegeeks.com/2017/12/some-factory-examples.html

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

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

相关文章

eclipse工程导入Android Studio

在eclipse中选中要导出的工程&#xff08;此工程在eclipse中最好不要有错误&#xff09;&#xff0c;右键选择Export->Generate Gradle build files 在本地工程里生成了一个build.gradle文件。 在AS中选择 导入成功后会生成一个import-summary.txt 导入成功。

idea中drl文件_得分DRL:在OptaPlanner中更快,更轻松

idea中drl文件对于OptaPlanner &#xff08; Drools Planner&#xff09;6.0.0.Beta1&#xff0c;我已经用更优雅的ConstraintMatch系统替换了ConstraintOccurrence。 结果是您的DRL评分文件为&#xff1a; 快多了 更容易读写 错误的发生率要低得多&#xff0c;因为它们使得…

超棒的Glide图片加载

GitHub开源&#xff1a;https://github.com/bumptech/glide 超棒的工具&#xff0c;竟然还可以加载.gif !!Glide完全基于Picasso&#xff0c;沿袭了其简洁风格&#xff0c;并在其基础上做了大量优化与改进。 1、Glide默认的Bitmap格式是RGB_565&#xff0c;而Picasso默认ARGB_…

开源GraphView的使用--数据统计

最近做室内定位需要绘出加速度传感器输出的三个方向的加速度曲线&#xff0c;找到了开源https://github.com/jjoe64/GraphView-Demos&#xff0c;省去了要重新学MatLab **。 在http://www.android-graphview.org/download--getting-started.html下载.jar包。 1、GraphView的使…

我的对象命名

这是最常见的辩论之一。 大多数人对此主题有自己的见解&#xff0c;却没人能真正说出哪个是正确的。 我当然不能&#xff0c;但是尽管如此&#xff0c;我还是决定与大家分享我的想法&#xff0c;投入两美分&#xff0c;也许对某人会有帮助。 当我创建一个新类时&#xff0c;我…

netbeans 定制代码_将NetBeans代码模板弯曲到我的意愿

netbeans 定制代码任何阅读过我关于NetBeans的文章的人都知道&#xff0c;我真的很喜欢NetBeans的许多功能。 但是&#xff0c;最近&#xff0c;我发现自己对NetBeans特定功能的特定问题越来越恼火。 最终&#xff0c;它使我烦恼不已&#xff0c;促使我开始研究如何根据自己的喜…

Java 9概览

对于许多Java 9来说&#xff0c;它似乎是一个维护版本&#xff0c;它推动了不能在Java 8中实现的项目Jigsaw。但是&#xff0c;随着JDK中的新模块系统以及与之相关的许多内部更改&#xff0c;Java 9也带来了开发人员工具箱中一些很棒的新内容。 以下是重点内容&#xff1a; JS…

adf开发_了解ADF Faces clientComponent属性

adf开发我相信大多数ADF开发人员都知道ADF Faces属性clientComponent 。 在本文中&#xff0c;我将展示该属性实际上如何影响组件渲染以及它如何改变其行为。 让我们开始考虑一个非常简单的示例&#xff1a; <af:inputText label"Label 1" id"it1" /&g…

Picocli 2.0:事半功倍

介绍 Picocli是一个单文件命令行解析框架&#xff0c;它使您几乎不需要任何代码即可创建命令行应用程序。 使用Option或Parameters注释应用程序中的字段&#xff0c;picocli将分别使用命令行选项和位置参数填充这些字段。 例如&#xff1a; Command(name "Greet", …

移动通信—无线波传播

无线波传播 发射天线或自然辐射源所辐射的无线电波,通过自然条件下的媒质到达接受天线的过程称为无线电波传播。无线电波与可见光、X射线与γ射线-.样同属于电磁波,它们都是以电场和磁场为其特征的- -种电场震动。电磁波的频谱范围很宽,从几赫到3X 1023Hz(波长从几十兆米到10-9…

使用Dropwizard度量标准监视和测量无功应用

在上一篇文章中&#xff0c;我们创建了一个简单的索引代码&#xff0c;该代码可以对ElasticSearch进行数千个并发请求。 监视系统性能的唯一方法是老式的日志记录语句&#xff1a; .window(Duration.ofSeconds(1)) .flatMap(Flux::count) .subscribe(winSize -> log.debug(…

移动通信-多径效应,多普勒效应,菲涅尔区,阴影效应,快衰落,慢衰落

多径效应 信号从发射端到接收端常有许多时延不同、损耗各异的传输路径&#xff0c;可以是直射、反射或是绕射。无线电波的多径效应是指不同路径的相同信号在按收端叠加会增大或减小接收信号能量的现象。 时间色散 在无线通信中&#xff0c;无线电波从发射端到接收端会经过直射、…

四旋翼

更新2018/11 1系统设计 硬件总体框架&#xff08;认识四旋翼的基本组成&#xff09; 机架主要的两种&#xff08;x型控制更难&#xff0c;动作灵活&#xff09; 十字型,X字型 桨 7040,8045&#xff08;常用&#xff09;&#xff0c;前四位直径&#xff0c;后四位角度 正反螺旋…

hotspot线程模型_Linux上的HotSpot GC线程CPU占用空间

hotspot线程模型以下问题将测试您对Linux操作系统上运行的Java应用程序的垃圾收集和高CPU故障排除的知识。 当调查过多的GC和/或CPU利用率时&#xff0c;此故障排除技术尤其重要。 它将假定您无权使用高级监控工具&#xff0c;例如Compuware dynaTrace甚至JVisualVM。 将来将介…

数字信号处理实验一

补充2019/10/26 (1)序列的加、减、乘、除和乘方运算。输入A[1 2 3 4]&#xff0c;B[3 4 5 6]&#xff0c;起点n0&#xff0c;求CAB&#xff0c;DA-B&#xff0c;EA.*B&#xff0c;FA./B&#xff0c;GA.^B&#xff0c;并用stem语句画出A&#xff0c;B&#xff0c;C&#xff0c;D…

SRP是骗局

根据罗伯特马丁 &#xff08; Robert Martin&#xff09;的 《 清洁法 》&#xff08; Clean Code&#xff09; &#xff0c;“ 单一责任原则 ”意味着“一个阶级应该只有一个改变的理由”。 让我们尝试解密这个模糊的语句&#xff0c;看看它如何帮助我们设计更好的面向对象软件…

数字信号处理实验二

补2019/11/2 &#xff08;1&#xff09;编写函数如xsiAdd(x1,n1,x2,n2),实现两个序列x1和x2的相加&#xff0c;其中x1的下标为n1n1s:nlf&#xff0c;x2的下标为n2n2s:n2f。绘制出该函数的图形。设x1&#xff08;n&#xff09;n,0≦n1≦9,x2(n)n,4≦n2≦15。 &#xff08;2&…

apache camel_使用Apache Camel发布/订阅模式

apache camel发布/订阅是一种简单的消息传递模式&#xff0c;其中&#xff0c;发布者将消息发送到某个频道&#xff0c;而无需知道谁将接收消息。 然后&#xff0c;通道负责将消息的副本传递给每个订户。 此消息传递模型可以创建松耦合和可伸缩的系统。 这是一种非常常见的消息…

Java 9:JShell

JShell是Java 9中引入的新工具&#xff0c;用于评估在命令行上输入的Java语句。 它是Java平台上第一个正式的REPL&#xff08;读取-评估-打印循环&#xff09;实现&#xff0c;非常适合尝试Java代码而无需启动IDE或编写完整的程序&#xff01; 要运行JShell&#xff0c;只需在…

三句话介绍清楚滑动窗口协议/GBN/SR

滑动窗口协议、GBN、SR之间不得不说的故事 首先我们来介绍什么是滑动窗口协议 滑动窗口协议&#xff08;Sliding Window Protocol&#xff09;&#xff0c;属于TCP协议的一种应用&#xff0c;用于网络数据传输时的流量控制&#xff0c;以避免拥塞的发生。该协议允许发送方在停…