回调/命令与事件监听器/观察者模式

发布于 2024-12-28 07:59:46 字数 909 浏览 1 评论 0原文

我正在尝试设计一个异步框架,并想知道人们认为回调模式与观察者模式的优缺点。

Callback pattern:

//example callback
public interface Callback{
    public void notify(MethodResult result);
}

//example method
public class Worker{
  public void doAsyncWork(Callback callback){
     //do work
     callback.notify(result);
  }
}

//example observer pattern
public interface EventListener{
   public void notify(MethodResult result);

}

public class Worker{
  private EventListener listener;
  public registerEventListener(EventListener listener){
   this.listener=listener;
  }
  public void doAsyncWork(){
     //do work
     listener.notify(result);
  }
}

我正在使用一个似乎使用这两种模式的框架。 EventListener 模式不是典型模式,因为它没有侦听器列表。这可以通过创建一个 CompositeListener 来轻松实现,该 CompositeListener 在侦听器的优先级以及如何处理向每个侦听器分配事件方面有自己的语义,例如为每个侦听器与串行通知生成一个新线程。 (我实际上认为这是一个好主意,因为它很好地分离了关注点,并且是对标准观察者/监听者模式的改进)。

关于什么时候应该使用它们有什么想法吗?

谢谢。

I'm trying to design an async framework and wanted to know what people think are the pros/cons of the callback pattern vs the observer pattern.

Callback pattern:

//example callback
public interface Callback{
    public void notify(MethodResult result);
}

//example method
public class Worker{
  public void doAsyncWork(Callback callback){
     //do work
     callback.notify(result);
  }
}

//example observer pattern
public interface EventListener{
   public void notify(MethodResult result);

}

public class Worker{
  private EventListener listener;
  public registerEventListener(EventListener listener){
   this.listener=listener;
  }
  public void doAsyncWork(){
     //do work
     listener.notify(result);
  }
}

I'm working with a framework which seems to use both of these patterns. The EventListener pattern is not the typical pattern as it doesn't have a list of listeners. This can easily be implemented though by creating a CompositeListener which has its own semantics on the priority of listeners and how to handle the distribution of events to each listener e.g. spawning a new thread for each listener vs serial notifications. (I actually think this is a good idea as its a good separation of concerns and is an improvement on the standard observer/listener pattern).

Any thoughts on when you should use each?

Thxs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不醒的梦 2025-01-04 07:59:46

命令、回调和观察者模式具有不同的语义:

  • 回调 - 通知单个调用者某些操作已完成并产生某些结果
  • 观察者 - 通知零到 n 个感兴趣的各方某些事件(例如例如,完成的操作)发生
  • 命令 - 将操作调用封装在对象中,从而使其可通过线路传输或可持久

在您的示例中,您可以结合回调和观察者模式来实现更大的 API 灵活性:

  1. 使用回调模式来触发操作并异步通知调用者触发的操作已完成。
  2. 使用事件/观察者模式让一些其他组件(触发操作)有机会在操作完成时收到通知。

Command, callback and observer patterns have different semantics:

  • callback - notifies a single caller that some operation finished with some result
  • observer - notifies zero to n interested parties that some event (for example a finished operation) happened
  • command - encapsulates a operation call in an object thus making it transferable over a wire or persist-able

In your example you could combine both callback and observer patterns to achieve greater API flexibility:

  1. Use the callback pattern to trigger operations and notify the caller asynchronously that the triggered operation finished.
  2. Use the event/observer pattern to give some other components (that did not trigger the operation) the chance to be notified when an operation finishes.
电影里的梦 2025-01-04 07:59:46

两种模式都很棒,选择哪一种取决于您要构建什么以及如何使用您的框架。

如果您正在尝试构建某种具有以下典型工作流程的发布-订阅系统:

  • 客户端启动异步任务并忘记它,
  • 多个处理程序在任务完成时收到通知

,那么观察者模式是一个自然的选择为你。当您正在构建框架时,您还应该考虑使用 EventBus 模式来实现松散耦合。

如果您只需要一个简单的异步执行,并且使用框架的典型流程是:

  • 启动异步任务
  • 在完成时执行某些操作

  • 启动异步任务
  • 执行某些操作
  • 等待其完成并执行某些操作

,那么您应该使用简单的 <代码>回调。

但为了实现更可用和更干净的 API,我建议您摆脱 Callback 抽象,并设计您的工作代码以返回某种 Future

public interface Worker<T> {

    Future<T> doAsync();

}

并且 Worker 可以按以下方式使用:

Future<Integer> future = worker.doAsync();

// some work here

Integer result = future.get(); // waits till async work is done

Future 可以是标准的 java 未来。但我建议您使用 guava 库中的 ListenableFuture

Both patterns are great and which one to choose depends on what are you going to build and how your framework will be used.

If you are trying to build some kind of publish-subscribe system with following typical flow of work:

  • client starts async task and forgets about it
  • multiple handlers receives notifications when task is completed

then Observer pattern is a natural choice for you. As you are doing a framework you should also consider using EventBus pattern to achieve loose coupling.

If you need nothing more than a simple asynchronous execution and a typical flow using of your framework is:

  • start async task
  • do something when it is completed

or

  • start async task
  • do something
  • wait till it is completed and do something

then you should go with simple Callback.

But in order to achieve more usable and clean API I'd recommend you to get rid of Callback abstraction and design your worker code to return a some kind of Future.

public interface Worker<T> {

    Future<T> doAsync();

}

And Worker can be used following way:

Future<Integer> future = worker.doAsync();

// some work here

Integer result = future.get(); // waits till async work is done

Future could be a standard java Future. But I'd suggest you to use ListenableFuture from guava library.

审判长 2025-01-04 07:59:46

我认为回调模式更好,因为它更简单,这意味着它更可预测,并且由于其自身的变异状态而不太可能出现错误。操作中的一个示例是 GWT 处理浏览器/服务器通信的方式

不过,您可能想使用泛型:

//example callback
public interface Callback<T> {
    public void notify(T result);
}

//example method
public class Worker{
  public void doAsyncWork(Callback<SomeTypeOrOther> callback){
     //do work
     callback.notify(result);
  }
}

I'd argue that the callback pattern is better as it is simpler which means it'll be more predictable and less likely to have bugs due to it's own mutating state. An example of this in operation would be the way GWT handles browser / server communication.

You might want to use generics though:

//example callback
public interface Callback<T> {
    public void notify(T result);
}

//example method
public class Worker{
  public void doAsyncWork(Callback<SomeTypeOrOther> callback){
     //do work
     callback.notify(result);
  }
}
烟酒忠诚 2025-01-04 07:59:46

让我们考虑一下 Lamp 和 Switch 的例子,看看观察者模式和命令模式之间的区别。

观察者模式

  • 开关是一个主题,一列灯是观察者,在其上开/关
    可以应用操作。
  • 这是一对多的关系。
  • 动作 ON/OFF 实际上是最简单形式的函数。
  • 不以最简单的形式提供对命令的封装。

命令模式

  • 另一方面,在命令模式中,动作 ON/OFF 变为命令
    类。

  • 命令类包含可以对其应用操作的接收器灯。

  • 命令模式通常提供一对一的关系,但是也可以
    也可以缩放以提供一对多。

  • 命令模式为命令提供了适当的封装。

Lets consider the example of Lamp and Switch to see the difference between observer and command pattern.

Observer Pattern

  • Switch is a Subject and a list of lamps are Observers on which ON/OFF
    actions can be applied.
  • It's a one to many relationship.
  • Actions ON/OFF are actually functions in its simplest form.
  • Does not provide encapsulation to commands in its simplest form.

Command Pattern

  • On the other hand in command pattern Actions ON/OFF becomes Command
    class.

  • Command class contains receiver Lamp on which action can be applied.

  • Command pattern is often provides one to one relationship however can
    be scaled to provide one to many as well.

  • Command pattern provides proper encapsulation to the command.

往事随风而去 2025-01-04 07:59:46
  • 回调:作为参数传递给函数的可执行代码,当特定事件发生时调用该函数。它可以用不同的编程语言以不同的形式实现,例如函数指针、匿名函数和监听器/观察者(面向对象范例)。它通常指的是单个可执行代码,但这不是必需的。一个反例:Android SDK(API级别29)中的SurfaceHolder接口允许使用addCallback()方法注册多个回调。
  • 侦听器/观察者:在面向对象的范式中,它是一个具有方法的对象,该方法作为参数传递给在特定事件发生时调用的函数。这是多个回调的一种可能实现。
  • 观察者模式:一种面向对象的软件设计模式,建议使用观察者/侦听器来将观察者类与被观察类解耦。

在您的具体代码中,Callback 和 EventListener 之间的唯一区别是:

  • 您只允许注册一个 Callback,但允许多个 EventListener
  • 回调注册与异步任务的执行同步,而 EventListener 注册则不然。

前者更简单,后者更灵活。如果您正在创建一个可重用的框架,那么后者更有意义。

命令设计模式是在对象中执行操作所需的所有信息的封装,它与用于通知事件的机制无关。

  • Callback: executable code passed as an argument to a function which is called when a specific event happens. It may be implemented in different forms in different programming languages, such as function pointers, anonymous functions and listeners/observers (object-oriented paradigm). It often refers to a single executable code, but that is not required. A counterexample: the SurfaceHolder interface in Android SDK (API level 29) allows the registration of multiple callbacks using the addCallback() method.
  • Listener/observer: in object-oriented paradigm, it is an object with a method which is passed as an argument to a function which is called when a specific event happens. It is one possible implementation of multiple callbacks.
  • Observer pattern: an object oriented software design pattern which recommends using observer/listeners in order to decouple the observer class from the observed class.

In your specific code, the only differences between Callback and EventListener are:

  • you allow registering only one Callback, but allow multiple EventListeners
  • Callback registration is synchronized with the execution of the async task, EventListener registration is not.

The former is simpler, the latter is more flexible. If you are creating a reusable framework, the latter makes more sense.

The Command design pattern is the encapsulation of all information needed to perform an action in an object and it is has nothing to do with the mechanism used to notify events.

丶情人眼里出诗心の 2025-01-04 07:59:46

观察者模式和命令模式几乎没有共同的意图,并且可以组合。但不同之处在于他们的动机。

观察者模式描述了如何建立主体观察者之间的关系。它并不专注于将命令创建为单独的类并对其进行参数化,以便可以存储命令对象并支持可撤消的操作。但这就是命令模式的作用。

命令模式描述了如何建立调用者命令接收者之间的关系。它并不关注如何支持任意数量的观察员以及如何管理他们。但这就是观察者模式的作用。

Both Observer and Command patterns share few common intentions and can be combined. But the difference is in their motivation.

Observer pattern describes how to establish the relationship between subject and observer. It didn't focus on creating a command as a separate class and parameterizing it so the command object can be stored and support undoable operations. But this is what the Command pattern does.

Command pattern describes how to establish the relationship between invoker, command, and receiver. It didn't focus on how to support any number of observers and how to manage them. But this is what the Observer pattern does.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文