1

我有一个 RequestHandler 类和一个 RequestListener 类。RequestHandler 创建一个 RequestListener 并将其传递给它自己的引用。RequestListener 依次调用 RequestHandler 上的方法来处理不同类型的请求(例如,handleTypeARequest()、handleTypeBRequest() 等)。不幸的是,RequestHandler 也调用 RequestListener 上的方法(例如 processNextRequest()),所以我有一个循环依赖:

class RequestHandler {
   RequestListener requestListener;
   ...
}

class RequestListener {
   RequestHandler requestHandler;
   ...
}

这意味着两者之间的耦合更紧密,通常被认为是代码异味。

一种解决方案是使用不同的对象来封装每个请求,而不是使用不同的方法。当出现提示时,RequestListener 可以处理请求并为其返回某种类型的 Request 对象。不幸的是,我不太喜欢这种方法,部分原因是更多对象和类增加了复杂性,部分原因是性能问题(这很重要);直接在 RequestHandler 上调用 handleXXXRequest() 方法比创建一堆对象要快得多,并且可能还维护一个堆栈以在需要时缓冲它们。

这个问题还有其他解决方案吗,而且,这真的是一个问题吗?

4

3 回答 3

3

是的,这真的有问题吗?

就好像您说,父 <-> 子引用存在问题,两者都相互引用。我不相信这里真的有问题。

于 2010-07-28T20:12:49.477 回答
1

您的编程语言很可能允许您转发声明类,从而使您能够越过语法错误部分。

如果是 C++,我会这样做:

class RequestListener;

class RequestHandler {
    RequestListener *requestListener;
    /* ... */
}

class RequestListener {
    RequestHandler *requestHandler;
    /* ... */
}

但是,请注意,如果您尝试递归地嵌套对象本身,这将是一个问题(因为您将获得无限大的结构):

class RequestListener;

class RequestHandler {
    RequestListener requestListener;
        // the compiler will complain about an incomplete type here
    /* ... */
}

class RequestListener {
    RequestHandler requestHandler;
    /* ... */
}

由于您只希望对象相互引用而不是相互包含,所以应该没问题。

于 2010-07-28T20:14:22.003 回答
0

事件允许您通知其他对象某些状态更改,而无需显式引用类。

class RequestListener
{
    public event EventHandler<RequestReceivedEventArgs> RequestReceived;

    public void ProcessNextRequest(object sender, RequestHandledEventArgs e)
    {
        // Process next request.
    }
}

class RequestDispatcher
{
    public event EventHandler<RequestHandledEventArgs> RequestHandled;

    public void DispatchRequest(object sender, RequestReceivedEventArgs e)
    {
        // Invoke correct RequestHandler class/method.

        // Raise RequestHandled event when request handler has finished.
    }
}

var listener = new RequestListener();
var dispatcher = new RequestDispatcher();

// Subscribe to each other's events.
listener.RequestReceived += dispatcher.DispatchRequest;
dispatcher.RequestHandled += listener.ProcessNextRequest;

上面的 C# 示例遵循.NET Framework 指南,因此非常冗长,但它应该说明类之间的解耦。我还引入了一个RequestDispatcher类,它负责调用正确的处理程序,而不是让侦听器处理这个问题。

如果不想创建额外的类,您可以将此模型剥离为您真正需要的东西。例如,您可以在侦听器中公开TypeARequestReceivedTypeBRequestReceived事件。然后您的请求处理程序方法可以直接订阅这些事件。

于 2010-07-29T12:33:12.627 回答