首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java重构代码复制

Java重构代码复制
EN

Stack Overflow用户
提问于 2017-10-26 01:31:04
回答 1查看 1.4K关注 0票数 0

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

我有一个类Foo,它解析从套接字接收到的网络消息/数据,并调用相应的onEvent()方法。Foo纯粹是网络消息的解析器,它对接收到的事件没有逻辑。无论谁想要添加这样的逻辑,都必须子类Foo并重写onEvent()方法。

代码语言:javascript
复制
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接口。接口与来自FooFoo方法匹配,但添加PluginContext ctx作为第一个参数。

代码语言:javascript
复制
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

代码语言:javascript
复制
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()中看到的那样。

现在,有许多代码重复,我想删除。

  1. 首先,Plugin接口和Foo类有着几乎相同的方法。实际上,Plugin接口需要有Foo拥有的所有onEvent方法,但使用PluginContext ctx作为额外的第一个参数。
  2. 另一个代码复制是在PluginSupporingFoo中。所有onEvent()方法几乎都是彼此的副本:

代码语言:javascript
复制
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方法,有这么多复制粘贴代码是令人沮丧的,如果需要的话,很难全部修改它们。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-27 00:49:53

哇..。这是一个不适合使用eventXX( foo, bar, baz)等的设计,因为每次添加新事件时,都必须添加相应的侦听器方法。

也许更好的设计是重构这一点,这样您的Foo类只有少数onEvent()方法,或者理想情况下只有一个接受新Event接口的Event方法。

代码语言:javascript
复制
public class Foo{

  void onEvent(Event e){ ... }

} 

public interface Event{
     Object[] getArgs();

     //other Event specific methods
     ...
}

然后,每个eventXX方法都将是Event接口的新实现。

代码语言:javascript
复制
public class Event2 implements Event{

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

插件也同样只能有一个方法。

代码语言:javascript
复制
interface Plugin{

   onEvent(PluginContext ctx, Event e);

}

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

处理程序可以检查事件的类型,也可以根据需要制作EventType或其他类型的鉴别器。

代码语言:javascript
复制
 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>,如果您想变得更好的话。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46944473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档