我有一个RequestHandler类和一个RequestListener类。 RequestHandler创建一个RequestListener并将其引用传递给它自己。 RequestListener依次调用RequestHandler上的方法来处理处理它们时不同类型的请求(例如handleTypeARequest(),handleTypeBRequest()等)。不幸的是,RequestHandler还调用RequestListener上的方法(例如processNextRequest()),所以我有一个循环依赖:
class RequestHandler {
RequestListener requestListener;
...
}
class RequestListener {
RequestHandler requestHandler;
...
}
这意味着两者之间的联系更紧密,通常被认为是代码气味。
一种解决方案是使用不同的对象来封装每个请求而不是不同的方法。当提示时,RequestListener可以处理请求并为其返回某种类型的Request对象。不幸的是,我并不喜欢这种方法,部分原因是因为更多的对象和类的复杂性,部分是因为性能问题(这里很重要);直接在RequestHandler上调用handleXXXRequest()方法比创建一堆对象要快得多,并且可能还需要维护一个堆栈来缓冲它们直到需要它们。
这个问题是否有其他解决方案,而且真的是一个问题吗?
答案 0 :(得分:3)
是的,这真的是个问题吗?
就像你说的那样,父母< - >存在问题。儿童参考,两者都互相参照。我不相信这里真的有问题。
答案 1 :(得分: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;
/* ... */
}
由于你只是希望对象互相引用而不是相互包含,所以你应该没问题。
答案 2 :(得分: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 Guidelines,因此非常详细,但它应该说明类之间的分离。我还介绍了一个RequestDispatcher
类,负责调用正确的处理程序,而不是让监听器处理这个。
如果不想创建其他类,则可以将此模型仅删除到您真正需要的内容。例如,您可以在侦听器中公开TypeARequestReceived
和TypeBRequestReceived
个事件。然后您的请求处理程序方法可以直接订阅这些事件。