如何避免在构造函数中使用它

时间:2010-03-23 19:39:00

标签: java design-patterns

我遇到这种情况:

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)

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()函数中调用发送者,例如发送回复。但我不想将发送者传递给监听器,因此我能想到的唯一方法是在实现监听器的类中包含发送者,因此产生上述客户端实现。有没有办法在构造函数中不使用'this'来实现这个目的?感觉很奇怪,我不喜欢它,因为我在完全构建之前将自己传递给一个对象(MessageReceiver)。另一方面,MessageReceiver不是从外部传递的,它是在内部构造的,但这是否“净化”了奇怪的模式? 我正在寻求一种替代方案或某种形式的保证,这是安全的,或者它可能适得其反的情况。

3 个答案:

答案 0 :(得分:6)

可以将Client的依赖项(例如MessageReceiver)注入其中,而不是让Client知道如何构建MessageReceiver

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

但是我建议我们考虑打破这两个类之间的循环依赖关系,听起来好像你的设计中存在某些东西。

this传递给第一个类的构造函数中的另一个类的真正原因是一个不好的做法是因为在完全构造之前允许对this的引用进行转义。

答案 1 :(得分:2)

只要this在施工前从未被引用,它就不会适得其反。但是,你永远不应该依赖这个假设。并发性是一个很重要的因素,以及您传递给它的代码的合同。

由于客户 是一个MessageReceiver,为什么不把它作为一个呢?

public Client extends MessageReceiver implements MessageListener{
    /* ... */
}

答案 2 :(得分:1)

我没有看到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");
    }
}

我认为标准的发布 - 订阅或观察者模式可能就是您所需要的 - 但如果不了解您尝试解决的问题的微妙之处,很难说清楚。