我有很多重复的代码,但我不知道如何正确地重构它。
我有一个类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接口。接口与来自Foo的Foo方法匹配,但添加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);
}现在,为了将事件分派给模块,我创建了一个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接口的对应的onEvent()方法将该事件分派给所有模块,并添加了一个额外的参数-- PluginContext ctx。有时还存在一个条件,即是否告诉模块一个事件,就像您在PluginSupporingFoo.onEvent2()中看到的那样。
现在,有许多代码重复,我想删除。
Plugin接口和Foo类有着几乎相同的方法。实际上,Plugin接口需要有Foo拥有的所有onEvent方法,但使用PluginContext ctx作为额外的第一个参数。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方法,有这么多复制粘贴代码是令人沮丧的,如果需要的话,很难全部修改它们。
发布于 2017-10-27 00:49:53
哇..。这是一个不适合使用eventXX( foo, bar, baz)等的设计,因为每次添加新事件时,都必须添加相应的侦听器方法。
也许更好的设计是重构这一点,这样您的Foo类只有少数onEvent()方法,或者理想情况下只有一个接受新Event接口的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() };
}
}插件也同样只能有一个方法。
interface Plugin{
onEvent(PluginContext ctx, Event e);
}现在,每当您需要添加一个新事件时,它只是一个新的事件实现,这些接口不需要任何额外的方法。
处理程序可以检查事件的类型,也可以根据需要制作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,我们甚至可以拥有一个处理程序Map<Class<? extends Event>, Function>,如果您想变得更好的话。
https://stackoverflow.com/questions/46944473
复制相似问题