简体   繁体   English

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

[英]Does the Observer pattern violate single responsibiliy principle?

If an application utilising the Observer design pattern has a subject class with the following responsibilities: 如果使用“观察者”设计模式的应用程序的subject类具有以下职责:

1) Managing and notifying observers (ie providing register and unregister functions and calling all observers notify functions) and 1)管理和通知观察者(即提供注册和注销功能并调用所有观察者通知功能);

2) Its original responsibility (ie what ever the class was doing before it was a subject ). 2)它的原始责任(即班级在成为subject之前所做的一切)。

Does this class violate the Single Responsibility Principle? 此类是否违反“单一责任原则”? It clearly has more than one responsibility but reading up on the SRP I am confused wrt 'reason for change' is this change at design time or run time? 它显然有多个职责,但请仔细阅读SRP,我很困惑“更改的原因”是在设计时还是在运行时更改?

Yes it does. 是的,它确实。 But.... 但....

Let's go back a little bit to the the big idea behind design patterns, which is basically helping the developer dealing with future pending changes more easily. 让我们再回顾一下设计模式背后的宏伟构想,它基本上是在帮助开发人员更轻松地应对将来的未决更改。

The level of granularity set for your design is up to you, the path to the golden middle should be guided by your common sense, experience and the scale of the application. 设计的粒度级别由您决定,通向黄金中间的路径应由您的常识,经验和应用程序规模来指导。

If changes to the distribution of your repository are seen ahead you could create a midiator (pub-sub) that will be responsible to distribute your changes to the observers. 如果可以预见到存储库分发的更改,则可以创建一个中介器(pub-sub),负责将更改分发给观察者。

Answering my own question because although bav's answer links to a great resource it doesn't answer the question. 回答我自己的问题,因为尽管bav的答案链接到大量资源,但却无法回答问题。 (Although watching the video give me the understanding which allows me to answer the question!) (尽管观看视频可以使我理解,但我可以回答问题!)

No, this is a misunderstanding of the Single Responsibility Principle (SRP). 不,这是对单一责任原则(SRP)的误解。

The responsibility in SRP refers to a customer role who may initiate a change request. SRP中的职责是指可以发起变更请求的客户角色 For example if a class Employee has the calculatePay() and displayEmployee() methods it could reasonably be assumed to violate SRP as calculatePay would 'belong' to the company accountant where as displayEmployee would belong to the reports clerk. 例如,如果某个类Employee具有calculatePay()displayEmployee()方法,则可以合理地认为它违反了SRP,因为calculatePay将“属于”公司会计,而displayEmployee将属于报告书记员。 This would mean two people with separate roles could request changes to a class. 这意味着两个角色不同的人可以请求更改班级。

The observer pattern does not add a new responsibility (as least not an SRP responsibility) as no customer role would care that this class publishes changes to its observers. 观察者模式不会添加新的责任(至少不是SRP责任),因为没有客户角色会关心此类是否将更改发布给其观察者。

No, the Observer design pattern does not violate the Single Responsibility Principle (SRP) . 不, Observer设计模式不违反Single Responsibility Principle (SRP)

What is a responsibility? 什么是责任?

"A responsibility denotes the obligation of an object to provide a certain behavior." “责任表示对象提供某种行为的义务。”
[Object-Oriented Analysis and Design, Grady Booch [et al.], page 600] [面向对象的分析和设计,Grady Booch [等],第600页]

But the SRP defines a responsibility differently, as a reason to change. 但是,SRP对责任的定义不同,这是变更的原因。 The SRP states that a class should have only one responsibility (reason to change). SRP指出,班级应该只负责一项责任(改变理由)。

This corresponds to the GoF principle of encapsulating things that change - a theme of many GoF design patterns. 这与GoF封装变化的事物的原理相对应-这是许多GoF设计模式的主题。 For example, the Strategy pattern encapsulates an algorithm (that can change) in a separate Strategy class. 例如,策略模式将算法(可以更改)封装在单独的策略类中。

The Observer pattern isn't about encapsulating things that change. 观察者模式与封装变化的内容无关。 It describes a way to define a one-to-many dependency between interacting objects without making the objects tightly coupled. 它描述了一种在不使对象紧密耦合的情况下定义交互对象之间一对多依赖性的方法。

For further discussion see the GoF Design Patterns Memory for learning object-oriented design & programming at http://w3sdesign.com . 有关进一步的讨论,请访问http://w3sdesign.com上的GoF设计模式内存,以学习面向对象的设计和编程。

In my opinion: Yes the observer pattern does violate the SRP (sometimes). 我认为:是的,观察者模式确实违反了SRP(有时)。

Imagine the following class, part of a MVC application (Java pseudo syntax): 想象一下以下类,它是MVC应用程序(Java伪语法)的一部分:

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

The first three methods are clearly related to managing the applications data while the last three methods are not. 前三种方法显然与管理应用程序数据相关,而后三种方法则无关。

The SRP states, a class should have only one reason to change[1]. SRP指出,一个类应该只有一个改变的理由[1]。 I can think of multiple reasons to change the observer methods where the management of the applications data should not be affected. 我可以想到多种原因来更改观察者方法,在这些方法中不应影响应用程序数据的管理。 Some examples: 一些例子:

  • I'd like to notify all observers in parallel for performance reasons. 由于性能原因,我想同时通知所有观察者。
  • I'd like to notify an observer via some message bus because a new view runs in some other process. 我想通过某种消息总线通知观察者,因为新的视图在其他过程中运行。
  • I'd like to register and unregister observers in parallel and thus need some other list implementation (one that is thread safe). 我想并行注册和注销观察者,因此需要其他一些列表实现(一个线程安全的列表实现)。

(One could argue, all this things can be hidden in an Observer itself. But registering an observer that allows to concurrently register other observers does not seem right either, IMO.) (一个人可能会争辩说,所有这些东西都可以隐藏在Observer本身中。但是,注册允许同时注册其他观察员的观察员,IMO也不正确。)

BTW, the observer pattern also violates the DRY (don't repeat yourself) principle , because you need to implement the registering, unregistering and notification mechanism (ie the loop over all observers) over and over again. 顺便说一句,观察者模式也违反了DRY(不要重复自己)的原则 ,因为您需要一遍又一遍地实现注册,注销和通知机制(即遍历所有观察者的循环)。

But: 但:

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] — [1]

So you have to decide for yourself and balance SRP and DRY with needless complexity. 因此,您必须自己决定,并以不必要的复杂性平衡SRP和DRY。


[1] The Principles of OOD by Robert C. Martin (aka Uncle Bob) and his book "Agile Software Development, Principles, Patterns, and Practices", chapter 8. [1] Robert C. Martin(又名Bob叔叔)和他的书“敏捷软件开发,原理,模式和实践”中的OOD原则,第8章。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM