Как избежать использования этого в конструкторе - PullRequest
2 голосов
/ 23 марта 2010

У меня такая ситуация:

interface MessageListener
{
   void onMessageReceipt(Message message);
}

class MessageReceiver
{
  MessageListener listener;
  public MessageReceiver(MessageListener listener, other arguments...)
  {
     this.listener = listener;
  }

  loop()
  {
    Message message = nextMessage();
    listener.onMessageReceipt(message);
  }
}

и я хочу избежать следующего шаблона: (используя this в конструкторе Client)

class Client implements MessageListener
{
   MessageReceiver receiver;
   MessageSender sender;

  public Client(...)
  {
    receiver = new MessageReceiver(this, other arguments...);
    sender = new Sender(...);
  }
  .
  .
  .
  @Override
  public void onMessageReceipt(Message message)
  {
     if(Message.isGood())
       sender.send("Congrtulations");
     else
       sender.send("Boooooooo");
  }
}

Причина, по которой мне нужны вышеуказанные функции, заключается в том, что я хочу вызвать отправителя внутри функции onMessageReceipt (), например, чтобы отправить ответ. Но я не хочу передавать отправителя в прослушиватель, поэтому я могу думать только о том, чтобы содержать отправителя в классе, который реализует прослушиватель, и, следовательно, вышеописанную реализацию Client. Есть ли способ достичь этого без использования «this» в конструкторе? Это кажется странным, и мне это не нравится, так как я передаю себя объекту (MessageReceiver) до того, как я полностью сконструирован. С другой стороны, MessageReceiver не передается извне, он создается внутри, но очищает ли это причудливый паттерн? Я ищу альтернативу или какую-то гарантию того, что это безопасно, или ситуации, в которых это может иметь неприятные последствия для меня.

Ответы [ 3 ]

6 голосов
/ 23 марта 2010

Зависимости Client (такие как MessageReceiver) могут быть внедрены в него, вместо того, чтобы Client знал, как построить MessageReceiver:

Client client = new Client(...);
MessageReceiver rcvr = new MessageReceiver(client, ...);
client.setMessageReceiver(rcvr);

Однако я бы посоветовал разобрать круговую зависимость между этими двумя классами, звучит так, как будто в вашем проекте что-то не так.

Настоящая причина, по которой передача this другому классу в конструкторе первого класса является плохой практикой, заключается в том, что вы позволяете ссылке на this сбежать до того, как она полностью будет построена.

2 голосов
/ 23 марта 2010

Это не будет иметь неприятных последствий для вас, пока на this никогда не ссылаются до строительства. Тем не менее, вы никогда не должны полагаться на это предположение. Важным фактором здесь является параллелизм, а также контракт для кода, которому вы его передаете.

Так как клиент является MessageReceiver, почему бы не сделать его одним?

public Client extends MessageReceiver implements MessageListener{
    /* ... */
}
1 голос
/ 23 марта 2010

Я не вижу, где используется MessageReceiver, поэтому в данный момент вы можете написать код без MessageReceiver, как это, и он будет фактически таким же:

interface MessageListener
{
    void onMessageReceipt(Message message);
}

class Client implements MessageListener
{
    MessageSender sender;

    public Client(...)
    {
        sender = new Sender(...);
    }
    .
    .
    .
    @Override
    public void onMessageReceipt(Message message)
    {
        if(Message.isGood())
            sender.send("Congrtulations");
        else
            sender.send("Boooooooo");
    }
}

Я думаю, что вам, вероятно, нужен стандартный шаблон публикации-подписки или Observer, но трудно понять, не понимая тонкостей проблемы, которую вы пытаетесь решить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...