gpt4 book ai didi

java - 使用代理模式编写服务器是个好主意吗?

转载 作者:搜寻专家 更新时间:2023-11-01 03:38:54 24 4
gpt4 key购买 nike

对于一个学校项目,我需要用 Java 编写一个简单的服务器,它持续监听传入目录并将文件从该目录移动到其他位置。服务器需要记录信息和错误消息,所以我想我可以为此使用代理模式。因此,我创建了以下 ServerInterface:

public interface ServerInterface extends Runnable {

public void initialize(String repPath, ExecutorInterface executor, File propertiesFile) throws ServerInitException;

public void run();

public void terminate();

public void updateHTML();

public File[] scanIncomingDir();

public List<DatasetAttributes> moveIncomingFilesIfComplete(File[] incomingFiles);

}

然后我创建了一个代表真实对象的实现 Server 和一个代表代理的类 ProxyServerServer 还有一个工厂方法,它创建一个 ProxyServer 对象,但将其作为 ServerInterface 返回。

代理对象上的 run 方法如下所示:

@Override
public void run(){

log(LogLevels.INFO, "server is running ...");

while( !stopped ){

try {

File[] incomingContent = scanIncomingDir();
moveIncomingFilesIfComplete(incomingContent);
updateHTML();
pause();

} catch (Exception e) {
logger.logException(e, new Timestamp(timestampProvider.getTimestamp()));
pause();
}

}

log(LogLevels.INFO, "server stopped");
}

try 语句中调用的函数只是记录一些内容,然后将调用传播到真实对象。到目前为止,一切都很好。但是现在我已经在代理对象中以这种方式实现了 run 方法,真实对象中的 run 方法变得过时了,因此它只是空的(相同用于 terminate-method)。

所以我问自己:可以吗?代理模式应该这样实现吗?

在我看来,我混淆了“真实”和“代理”行为……通常情况下,真实服务器应该“卡在”while 循环中而不是代理服务器,对吧?我试图避免将其混淆,但两种方法都不令人满意:

  • 我可以在真实对象中实现 run 方法,然后将代理对象移交给真实对象,以便在 while 循环期间仍然能够记录。但随后真实对象会进行一些日志记录,这是我首先尝试通过编写代理来避免的。

  • 我可以说,只有 Proxy-Server 是 Runnable,因此从接口(interface)中删除了 runterminate,但这会打破代理模式。

我应该使用其他设计吗?还是我看到了一个根本没有问题的问题?

最佳答案

您的思考方式绝对正确。你想到了一个有趣的想法。

如您所述,日志记录 等功能是我们在 Aspect Oriented programming 中称为横切关注点 的示例。 .

  • 横切关注点是将在许多对象中使用的要求。

. .因此,它们倾向于破坏面向对象的编程。这是什么意思?

  • 如果您尝试创建一个类,该类完全是关于将文件从位置 A 移动到位置 B,并且执行此操作的方法首先讨论日志记录(然后是事务,然后是安全性),那么这不是很OO是吗?它打破了单一职责原则。

进入面向切面编程

这就是我们拥有 AOP 的原因 - 它的存在是为了模块化和封装这些横切关注点。它的工作原理如下:

  • 定义我们希望应用横切功能的所有位置。
  • 使用拦截设计模式“编织”该功能。

我们可以使用 AOP“编织”需求的方式

  • 一种方法是使用您所描述的 Java DynamicProxy。这是例如 Spring Framework 中的默认设置。这仅适用于接口(interface)。
  • 另一种方法是使用字节码工程库,例如 asm、cglib、Javassist - 它们会拦截类加载器以在运行时提供新的子类。
  • 第三种方法是使用编译时编织——在编译时更改代码(或字节码)。
  • 另一种方法是使用 java 代理(JVM 的一个参数)。

AspectJ 支持后两个选项。

总结:

听起来好像您正在转向面向方面的编程 (AOP),所以请检查一下。另请注意 Spring Framework有很多功能可以简化 AOP 的应用,但在您的情况下,考虑到这是一项学校作业,最好深入研究 AOP 本身背后的核心概念。

注意:如果您正在构建生产级服务器,日志记录可能是一个成熟的功能,因此值得使用 AOP。 .在其他情况下,它可能足够简单,只需内嵌即可。

关于java - 使用代理模式编写服务器是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20339780/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com