Как разрешить эту круговую, двунаправленную зависимость? - PullRequest
0 голосов
/ 29 июля 2010

У меня есть класс RequestHandler и класс RequestListener. RequestHandler создает RequestListener и передает ему ссылку на себя. RequestListener, в свою очередь, вызывает методы RequestHandler для обработки запросов разных типов при их обработке (например, handleTypeARequest (), handleTypeBRequest () и т. Д.). К сожалению, RequestHandler также вызывает методы RequestListener (например, processNextRequest ()), поэтому у меня есть циклическая зависимость:

class RequestHandler {
   RequestListener requestListener;
   ...
}

class RequestListener {
   RequestHandler requestHandler;
   ...
}

Это означает более тесную связь между ними и, как правило, считается запахом кода.

Одним из решений было бы использование разных объектов для инкапсуляции каждого запроса вместо разных методов. RequestListener может, когда будет предложено, обработать запрос и вернуть для него некоторый тип объекта Request. К сожалению, мне не очень нравится этот подход, частично из-за дополнительной сложности большего количества объектов и классов и частично из-за проблем с производительностью (которые имеют значение здесь); Вызов методов handleXXXRequest () в RequestHandler напрямую намного быстрее, чем создание группы объектов и, возможно, также поддержка стека для их буферизации до тех пор, пока это не потребуется.

Существуют ли другие решения этой проблемы, а также, действительно ли это 1009 * проблема?

Ответы [ 3 ]

3 голосов
/ 29 июля 2010

Да, это действительно проблема?

Это как если бы вы сказали, что есть проблема с родительскими <-> дочерними ссылками, где обе содержат ссылку друг на друга.Я не верю, что здесь действительно есть проблема.

1 голос
/ 29 июля 2010

Ваш язык программирования, скорее всего, позволяет вам пересылать объявления классов, что позволяет вам пройти часть синтаксической ошибки.

Если бы это был C ++, я бы сделал что-то вроде этого:1005 * Однако, обратите внимание, что было бы проблемой, если бы вы попытались рекурсивно вкладывать сами объекты (поскольку вы получили бы бесконечно большую структуру):вместо того, чтобы содержать друг друга, у вас все будет в порядке.

0 голосов
/ 29 июля 2010

События позволяют вам уведомлять другие объекты об определенных изменениях состояния без явной ссылки на класс.

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 в своем слушателе. Тогда ваши методы-обработчики запросов могут подписаться непосредственно на эти события.

...