观察者模式是否违反单一职责原则?

Does the Observer pattern violate single responsibiliy principle?

如果使用观察者设计模式的应用程序具有 subject class 并具有以下职责:

1) 管理和通知观察者(即提供注册和注销函数并调用所有观察者通知函数)和

2) 它的原始职责(即 class 在成为 subject 之前所做的一切)。

这class是否违反了单一职责原则?它显然有不止一项责任,但阅读 SRP 我很困惑 'reason for change' 这种变化是在设计时还是在 运行 时?

是的。 但是....

让我们稍微回顾一下设计模式背后的重要思想, 这基本上可以帮助开发人员更轻松地处理未来的待定更改。

为您的设计设置的粒度级别由您决定,通往黄金中间的路径应以您的常识、经验和应用程序的规模为指导。

如果提前看到对存储库分发的更改,您可以创建一个中间人 (pub-sub),负责将您的更改分发给观察者。

回答我自己的问题,因为尽管 bav 的回答链接到一个很好的资源,但它没有回答问题。 (虽然看视频让我有了理解,让我可以回答这个问题!)

不,这是对单一职责原则 (SRP) 的误解。

SRP 中的职责 是指可以发起变更请求的客户角色。 例如,如果 class Employee 具有 calculatePay()displayEmployee() 方法,则可以合理地假设它违反了 SRP,因为 calculatePay 会 'belong'公司会计师,其中 displayEmployee 属于报告文员。这意味着具有不同角色的两个人可以请求更改 class。

观察者模式不会添加新的责任(至少不是 SRP 责任),因为没有客户角色会关心此 class 向其观察者发布更改。

不,Observer 设计模式不违反 Single Responsibility Principle (SRP)

什么是责任?

"A responsibility denotes the obligation of an object to provide a certain behavior."
[Object-Oriented Analysis and Design, Grady Booch [et al.], page 600]

但是 SRP 以不同的方式定义责任,作为改变的理由。 SRP 指出 class 应该只有一个责任 (更改原因)。

这符合GoF原则 封装变化的事物 - 许多 GoF 设计模式的主题。 比如Strategy模式封装了一个算法 (可以更改)在单独的策略中 class.

观察者模式不是关于封装变化的事物。 它描述了一种在不使对象紧密耦合的情况下定义交互对象之间的一对多依赖关系的方法。

进一步的讨论参见GoF Design Patterns Memory学习 面向对象的设计与编程 http://w3sdesign.com.

在我看来:是的,观察者模式确实违反了 SRP(有时)。

想象以下 class,MVC 应用程序的一部分(Java 伪语法):

class Model {
    void setDateOfBirth(Date);
    Date getDateOfBirth();
    int getAge(); // calculated from date of birth
    void registerObserver(Observer);
    void unregisterObserver(Observer);
    void notifyObservers();
}

前三种方法显然与管理应用程序数据相关,而后三种方法则无关。

SRP 指出,class 应该只有一个更改理由[1]。我可以想到多种原因来更改不应影响应用程序数据管理的观察者方法。一些例子:

  • 出于性能原因,我想同时通知所有观察者。
  • 我想通过消息总线通知观察者,因为新视图在其他进程中运行。
  • 我想并行注册和取消注册观察者,因此需要一些其他列表实现(一个线程安全的)。

(有人可能会争辩说,所有这些东西都可以隐藏在 Observer 本身中。但是注册一个允许同时注册其他观察者的观察者似乎也不正确,IMO。)

顺便说一句,观察者模式也违反了DRY (don't repeat yourself) principle,因为你需要一遍又一遍地实现注册、注销和通知机制(即所有观察者的循环)。

但是:

Should these two responsibilities be separated? That depends upon how the application is changing. […] If […] the application is not changing in ways that cause the two responsibilities to change at different times, then there is no need to separate them. Indeed, separating them would smell of Needless Complexity. — [1]

所以你必须自己决定并平衡 SRP 和 DRY 以及不必要的复杂性。


[1] The Principles of OOD Robert C. Martin(又名鲍勃大叔)和他的书 "Agile Software Development, Principles, Patterns, and Practices",第 8 章。