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

时间:2015-02-02 16:08:58

标签: design-patterns

如果使用Observer设计模式的应用程序具有subject类,其职责如下:

1)管理和通知观察员(即提供注册和取消注册功能,并呼叫所有观察员通知功能)和

2)它最初的责任(即班级在subject之前所做的事情。)

此课程是否违反单一责任原则?它显然有不止一个责任,但阅读SRP我很困惑,因为改变的原因'这是设计时或运行时的变化吗?

4 个答案:

答案 0 :(得分:0)

是的。 但....

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

为您的设计设置的粒度级别取决于您,通往黄金中间的道路应遵循您的常识,经验和应用程序的规模。

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

答案 1 :(得分:0)

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

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

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

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

答案 2 :(得分:0)

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

责任是什么?

  

“责任是指对象提供的义务   某种行为。“   [面向对象的分析与设计,Grady Booch [等],第600页]

但是SRP将责任定义为不同的,作为改变的理由。 SRP声明一个班级应该只有一个责任 (理由改变)。

这对应于 GoF原则 封装变化的东西 - 许多GoF设计模式的主题。 例如,策略模式封装了算法 (可以改变)在一个单独的战略类中。

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

有关进一步的讨论,请参阅GoF设计模式记忆以进行学习 面向对象的设计&编程 http://w3sdesign.com

答案 3 :(得分:0)

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

想象一下以下类,它是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指出,一个班级应该只有一个改变的理由[1]。我可以想到多种原因来改变应用程序数据的管理不应受到影响的观察者方法。一些例子:

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

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

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

<强>可是:

  

这两项责任应该分开吗?这取决于应用程序的变化方式。 [...]如果应用程序没有以导致两个职责在不同时间发生变化的方式发生变化,那么就没有必要将它们分开。实际上,将它们分开会闻到 Needless Complexity 。    - [1]

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

罗伯特·C·马丁(又名鲍勃叔叔)和他的着作“敏捷软件开发,原则,模式和实践”,第8章

[1] The Principles of OOD