0

使用传统的侦听器回调模型。我有几个收集各种东西的听众。每个听众收集的东西都在内部结构中的听众内部。

问题是我希望一些听众知道其他听众的一些“东西”。

我强制执行侦听器注册顺序,因此如果我故意以某种顺序注册事件,稍后的侦听器可以确保先前的侦听器更新了它的内容并以某种方式访问​​它以执行更多操作。

我对此的第一次尝试是让每个侦听器存储对它所依赖的侦听器的引用。所以我按照没有依赖的顺序注册监听到有之前注册依赖的监听,然后在各种方法中设置监听之间的引用。

我开始意识到这种感觉有多糟糕,我想知道以前是否曾以某种方式走过这条路。当一个听众需要访问另一个听众的东西时,什么是更合适的模式?

这里有一些伪代码来说明:

interface Listener { onEvent(char e); }

class A implements Listener {
  private int count;
  public void onEvent(char  e) { if(e == 'a') count++; }
  public int getCount() { return count; }
}

class B implements Listener {
 private int count;
 // private A a;
 // private void setA(A a) { this.a = a; }

 public void onEvent(char  e) { if(e == 'b') count++; }
 public int getCount() { return count; }
 public int getAPlusBCount() {
   // We know B count, but we don't know A so how would we change this 
   // so B is A aware? Or not even aware, just somehow coupled? This
   // is the question
   // return a.getCount() + count;
 }

 public void doConditionalHere() {
  // Do some condition in B that relies on the state of data in A
  int acount = 0; // a.getCount(); ???
  if(acount % 2 == 0) {
   this.count--;
  }
 }
}

class Run {
 A a = new A();
 B b = new B();
 List listeners = new List();
 listeners.add(a);
 listeners.add(b);

 // The ugly way I add coupling right now is to keep a reference to A
 // inside B. It's commented out because I am hoping there is a more intelligent approach
 // b.setA(a);

 for(char c : "ababbabab") {
   for(listener : listeners) {
     listener.onEvent(c);
   }
 }
}
4

3 回答 3

2

您在这里描述了很多耦合。最好的办法是消除所有这些反向通道依赖,但如果做不到这一点,也许你可以让那些有依赖的人不在初始侦听器列表上侦听,而是在它们所依赖的任何东西上侦听。或者你可以让他们等到他们收到所有信号。

您可以通过让侦听器识别他们所依赖的对象来自动化依赖管理。侦听器列表将不按插入顺序排序,而是确保依赖对象遵循它们的依赖关系。您的侦听器界面如下所示:

interface Listener {
  String getId();
  Collection<String> getDependencies();
  onEvent(char e);
}

或者只是有参考,像这样:

interface Listener {
  Collection<Listener> getDependencies();
  onEvent(char e);
}
于 2008-11-09T01:21:18.170 回答
1

“我们如何改变这一点,让听众 B 知道听众 A?或者甚至不知道,只是以某种方式耦合?”

您通常不希望像这样耦合两个“对等”对象。您希望两个对等方依赖于共同点。

更深层次的问题是听众 A 或听众 B 如何处理他们收集的所有信息?

Listener 经常做两件事:收集数据并采取行动。通常这两件事需要分开。听众应该倾听和收集并做更多的事情。侦听器可以激活其他一些对象。

您可能拥有的只是一个具有多个操作(A 和 B)的侦听器。然后,侦听器可以向 A 和 B 提供适当的计数。它向 A 提供“a”计数。它向 B 提供“a”或“b”计数。

于 2008-11-10T02:53:23.117 回答
1

为什么没有一个中心对象来跟踪所有侦听器类的 onEvent 方法被触发了多少次

 public interface CountObserver {

 public void updateCount(String className);
 public int getCount(String className);
}

public class CentralObserver implements CountObserver {

 private int aCount;
 private int bCount;

 public void updateCount(String className) {

 //There's probably a better way to do this than using
 //all these if-elses, but you'll get the idea.

  if (className.equals("AclassName")) {
   aCount++;
  }
  else if (className.equals("BclassName")) {
   bCount++;
  }
 }

 public int getCount(String className) {

  if (className.equals("AclassName")) {
   return aCount;
  }
  else if (className.equals("BclassName")) {
   return bCount;
  }
}

class A implements Listener {

 CountObserver countObserver;

 public void registerObserver (CountObserver countObserver) {

  this.countObserver = countObserver;
 }

 public void onEvent(char e) {

  if(e == 'a') {

   countObserver.updateCount (this.getClass.getName);
  }
 }

}

//Same thing for B or any other class implementing Listener. Your Listener interface should, of 

//course, have a method signature for the registerObserver method which all the listener classes 

//will implement.

class Run {

 private A a;
 private B b; 
 private CountObserver centralObserver;

 public runProgram () {

  centralObserver = new CentralObserver();
  a.registerObserver(centralObserver);
  b.registerObserver(centralObserver);

 //run OnEvent method for A a couple of times, then for B

 }

 public int getAcount () {

 return centralObserver.getCount(a.getClass.getName());
 }

 public int getBcount () {

 return centralObserver.getCount(b.getClass.getName());
 }
} 
 //To get the sum of all the counts just call getAcount + getBcount. Of course, you can always  add more listeners and more getXCount methods
于 2008-11-10T21:26:17.550 回答