java - "Extending"实例创建后的匿名类

标签 java design-patterns anonymous-class

假设我必须为 Request 期间发生的事件分配事件处理程序。该 API 公开了一个抽象类 RequestHandlerAPIAdapter 和一个接口(interface) RequestHandlerAPI 以手动定义事件处理程序。 RequestHandlerAPIAdapter 实现了 RequestHandlerAPI。适配器仅存在,因此我可以执行以下操作:

client.setRequestHandler(new RequestHandlerAPIAdapter(Request request) {
    // override some or all inherited methods
});

请注意,适配器只允许我处理我感兴趣的事件,而忽略其他事件。例如,如果我只想在发送请求时做某些事情,而不关心正在处理或响应到达时会发生什么,我只能为 onRequestSent 指定一个处理程序并离开onRequestProcessingonResponseArrived。这种设计模式可以满足大多数现实世界的需求。

现在假设我事先不知道我需要处理什么事件,我可能会在创建 的匿名实例之后决定将来是否应该手动处理 onResponseArrived RequestHandlerAPIAdapter。将需要一个新的 RequestHandlerAPIAdapter 实例,我将不得不重复 onRequestSent 的定义。我知道这听起来很奇怪,也许开发人员永远不需要以这种方式编写代码,但我想知道在这种情况下是否有防止代码重复的解决方法。

我想出的一个解决方案是创建一个实现RequestHandlerAPI 或扩展RequestHandlerAPIAdapter 的具体类,为每个继承的方法定义公共(public)功能接口(interface),为刚刚定义的所有功能接口(interface),并为请求期间可能发生的每个事件添加方法 setHandler

下面是此类的代码:

public class RequestHandlerConcreteAdapter implements RequestHandlerAPI {
    private HandleOnRequestSent onRequestSent = null; // or may be an empty lambda expression that does nothing
    private HandleOnRequestProcessing onRequestProcessing = null;
    private HandleOnResponseRetrieved onResonseRetrieved = null;

    public interface HandleOnRequestSent {
        void onRequestSent (Request request);
    }

    public interface HandleOnRequestProcessing {
        void onRequestProcessing (Request request);
    }

    public interface HandleOnResponseRetrived {
        void onResponseRetrived (Request request, Response response);
    }

    @Override
    public void onRequestSent (Request request) {
        onRequestSent.onRequestSent(request);
    }

    public RequestHandlerConcreteAdapter setHandler (HanldeOnRequestSent h) {
        onRequestSent = h;
        return this; // allows us to chain methods
    }

    @Override
    public void onRequestProcessing (Request request) {
        onRequestProcessing.onrequestProcessing(request);
    }

    // overloaded
    public RequestHandlerConcreteAdapter setHandler (HanldeOnRequestProcessing h) {
        onRequestProcessing = h;
        return this; // allows us to chain methods
    }

    // and a pair to handle onResponseRetrived
}

这允许我做这样的事情:

RequestHandlerConcreteAdapter adapter = new RequestHandlerConcreteAdapter ();

adapter.setHandler ( (RequestHandlerConcreteAdapter.HandleOnRequestSent) (request) -> {
    //do something here
});

client.setRequestHandler (adapter);

// and at a later time
adapter.setHandler ( (RequestHandlerConcreteAdapter.HanldeOnResponseRetrieved) (request, response) -> {
    // do something here
});

client.setRequestHandler (adapter);

我会寻找各种可能性来避免做我上面所做的事情,因为这个解决方案对我来说太脏了。另外,我想知道我所做的是否是 Java 中已知的设计模式。

总而言之,我想知道是否有更简洁的方法来实现上面的代码正在做的事情,如果没有,您能否建议对代码进行一些改进,使其看起来不那么脏?

最佳答案

在我看来,您只是在寻找 Decorator pattern .实现 RequestHandlerAPIDecorator这是用 RequestHandlerAPI 的实例创建的并代表所有onRequest<DoSomething>调用它。要覆盖某些操作,子类化 RequestHandlerAPIDecorator并覆盖其中一种方法。

沿线的东西:

 public abstract class RequestHandlerAPIDecorator implements RequestHandlerAPI {

     protected final RequestHandlerAPI delegate;

     public RequestHandlerAPIDecorator(RequestHandlerAPI delegate) {
         this.delegate = Objects.requireNonNull(delegate, "delegate must not be null.");
     }

     public void onRequestProcessing(Request request) {
         delegate.onRequestProcessing(request);
     }

     // Etc. You IDE will happily generate delegate methods for you.
 }

现在如果你想覆盖,说“请求已发送”处理一些现有的 RequestHandlerAPI ,你只需要做:

 RequestHandlerAPI decoratedRequestHandler = 
     new RequestHandlerAPIDecorator(existingRequestHandler) {
         public void onRequestSent(Request request) {
             System.out.println("Request is sent.");
         }
     });

您可以从头开始实现处理或另外做一些事情,调用 delegate.onRequestSent(request)之后。

关于java - "Extending"实例创建后的匿名类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49810963/

相关文章:

java - 设计模式 - 使用通用对象来更新 GUI

java - 需要帮助使这些类使用访问者模式和泛型

javascript - cometd 和 jQuery

java - 在单独的线程中运行逻辑仍然锁定 UI - Java

java - 我的 servlet-mapping 直接匹配默认 servlet

java - OpenGL ES 2.0 - 用纹理画线?

java - @ComponentScan 未检测到模块路径中的类

java - Libgdx - 加载字体会减慢游戏速度

c++ - 我什么时候需要 C++ 中的匿名类?

java - 加斯顿和阿尔方斯示例 : How does the bowBack get accessed?