gpt4 book ai didi

Java重构代码重复

转载 作者:行者123 更新时间:2023-12-02 12:05:16 26 4
gpt4 key购买 nike

我有很多重复的代码,但我不知道如何正确重构它。

我有一个类Foo,它解析从套接字接收的网络消息/数据并调用相应的onEvent()方法。 Foo 纯粹是网络消息的解析器,它没有关于对其接收到的事件采取什么操作的逻辑。想要添加此类逻辑的人必须继承 Foo 并重写 onEvent() 方法。

abstract class Foo {
void processNetwotkMessage(String message) {
...
onEvent1(arg1, arg2, arg3)
reutn;
...
onEvent2(arg4);
return;
...
onEvent3()
return;
...
onEvent999(arg1337);
}

abstract protected void onEvent1(Arg1 arg1, Arg2 arg2, Arg3 arg3);
abstract protected void onEvent2(Arg4 arg4);
abstract protected void onEvent3();
...
abstract protected void onEvent999(Arg1337 arg1337);
}

现在,我的程序应该是模块化的,我有许多单独的模块类想要接收这些事件并处理它们。这些模块实现 Plugin 接口(interface)。该接口(interface)与 Foo 中的 onEvent() 方法匹配,但添加 PluginContext ctx 作为第一个参数。

interface Plugin {
void onEvent1(PluginContext ctx, Arg1 arg1, Arg2 arg2, Arg3 arg3);
void onEvent2(PluginContext ctx, Arg4 arg4);
void onEvent3(PluginContext ctx);
...
void onEvent999(PluginContext ctx, Arg1337 arg1337);
}

现在,为了将事件分派(dispatch)到模块,我创建了一个 Foo 的模块感知子类,名为 PluginSupporingFoo

class PluginSupporingFoo extends Foo implements PluginContext {
List<Plugin> plugins;

@Override
protected void onEvent1(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
synchronized (plugins) {
for (Plugin p : plugins) {
p.onEvent1(this, arg1, arg2, arg3);
}
}
}

@Override
protected void onEvent2(Arg4 arg4) {
synchronized (plugins) {
for (Plugin p : plugins) {
if (PluginIsAllowedToBeAwareOfThisEvent(p, arg4)) {
p.onEvent2(this, arg4);
}
}
}
}

@Override
protected void onEvent3() {
synchronized (plugins) {
for (Plugin p : plugins) {
p.onEvent3(this);
}
}
}

...

@Override
protected void onEvent999(Arg1337 arg1337) {
synchronized (plugins) {
for (Plugin p : plugins) {
p.onEvent999(this, arg1337);
}
}
}
}

如您所见,每当 Foo 调用 onEvent() 方法之一时,PluginSupporingFoo 中的重写方法就会被调用,然后调度通过调用 Plugin 接口(interface)相应的 onEvent() 方法,并添加一个额外参数 - PluginContext ctx,将此事件发送给所有模块。有时还存在是否向模块告知事件的条件,就像您在 PluginSupporingFoo.onEvent2() 中看到的那样。

现在,我想删除大量重复代码。

  1. 首先,Plugin 接口(interface)和 Foo 类具有几乎相同的方法。事实上,Plugin 接口(interface)需要具有 Foo 具有的所有 onEvent 方法,但首先需要使用 PluginContext ctx 作为额外的方法论证。

  2. 另一个重复代码位于 PluginSupporingFoo 中。所有 onEvent() 方法几乎都是彼此的副本:

.

protected void on${EventName} ( ${ArgList} ) {
synchronized (plugins) {
for (Plugin p : plugins) {
${ OPTIONAL: if (filter(p, ${ArgList}.arg1)) { }
p.on{EventName}(this, ${ArgList}.allArgs);
${ OPTIONAL: } }
}
}
}

考虑到有很多 onEvent 方法,有这么多复制粘贴代码是令人沮丧的,而且如果需要的话很难全部修改它们。

最佳答案

哇...这是一个糟糕的设计 eventXX( foo, bar, baz)等等,因为每次添加新事件时,您都必须添加相应的监听器方法。

也许更好的设计是重构它,以便您的 Foo类只有几个或最好有一个 onEvent()方法采用新的 Event界面

public class Foo{

void onEvent(Event e){ ... }

}

public interface Event{
Object[] getArgs();

//other Event specific methods
...
}

然后每个 eventXX方法将是 Event 的新实现界面。

public class Event2 implements Event{

public Object[] getArgs(){
//Arg4 like in your code
return new Object[]{ new Arg4() };
}
}

插件也可以类似地只有 1 个方法

interface Plugin{

onEvent(PluginContext ctx, Event e);

}

现在,每当您需要添加新事件时,它只是一个新的事件实现,并且这些接口(interface)不需要任何额外的方法。

处理程序可以检查事件的类型,或者您可以创建 EventType或您希望的其他类型的鉴别器。

 class MyPlugin implements Plugin{
public void onEvent(PluginContext ctx, Event e){
//this is only useful if we only care about a few types
if( e instanceOf Event2){
//we know this is Arg4
Arg4 arg4 = (Arg4) e.getArgs()[0];
...
}

}
}

现在,有了 Java Lambda,我们甚至可以拥有一个处理程序 Map<Class<? extends Event>, Function>如果你想变得更花哨。

关于Java重构代码重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46944473/

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