Overview
In the process of building software, we need to establish a "Notification dependency" for some objects-the state of an object (target object) changes, and all dependent objects (Observer objects) will be notified. If such dependency is too tight, the software cannot well resist changes. Using object-oriented technology, you can weaken this dependency and form a stable dependency. To achieve loose coupling of the software architecture.
A software system often requires that some other objects change accordingly when the state of an object changes. There are many design solutions to achieve this, but in order to make the system easy to reuse, we should choose a low coupling design. Reducing the coupling between objects is conducive to the reuse of the system, but at the same time, the designer needs to make the objects with low coupling degrees consistent with the action to ensure a high degree of collaboration ). The observer pattern is the most important in various design schemes that meet this requirement.
Intention
Defines a one-to-many dependency between objects. When the status of an object changes, all objects dependent on it are notified and automatically updated. [Gof design patterns]
<Design Pattern> structure chart
Figure 1 Structure of the observer Mode
Role description:
Subject (object interface observed)
Specifies the unified interface of concretesubject;
Each subject can have multiple observers;
Concretesubject (object to be observed)
Maintains a list of references to all specific observers;
When the status changes, a notification is sent to all registered observers.
Observer (Observer Interface)
Specifies the unified interface of concreteobserver;
Defines an update () method, which is called when the state of the object to be observed changes.
Concreteobserver (Specific observer)
Maintain a reference to concretesubject;
Synchronization between the specified status and concretesubject;
Implement the observer interface to receive concretesubject notifications through the update () method.
Examples in life
The observer defines the one-to-many relationship between objects. When the State of an object changes, all objects dependent on it are notified and automatically updated. The auction demonstrates this mode. Each bidder has a digital sign for bidding. When the auctioneer started the auction, he observed whether there was a sign raising his bid. Each acceptance of a new bid changes the current price of the auction and broadcasts new bids to all bidders.
Figure 2 use the observer mode of the auction example
Example:
The traffic lights at the crossroads, pedestrians and drivers are watching the changes of the traffic lights to act. The driver sees the light turns left and the pedestrians see the green light crossing the road. This is exactly in our observer mode, drive and pedestrian are specific observers, while pilotlamp is the observer interface and trafficlight. First, let's look at the example diagram:
CodeDesign:
Create pilotlamp. CS First:
Public interface pilotlamp {// <summary> // green light // </Summary> void turnon (); /// <summary> /// notice /// </Summary> string notice {Get; Set ;}}
Create delegateevent. CS again:
Public Delegate void eventhandler ();
Create trafficlight. CS again:
Public class trafficlight: pilotlamp {public event eventhandler notices; private string notice; # region greenlight member public void turnon () {If (notices! = NULL) Notices ();} Public String notice {get {return notice;} set {notice = value ;}# endregion}
Create driver. CS again:
Public class driver {private string name; private pilotlamp greenlight; Public Driver (string name, pilotlamp greenlight) {This. name = Name; this. greenlight = greenlight;} public void goleft () {console. writeline (string. format ("{1} driver, {0}, please drive to the left. ", Greenlight. notice, name ));}}
Create pedestrian. CS again:
Public class pedestrian {private string name; private pilotlamp greenlight; Public pedestrian (string name, pilotlamp greenlight) {This. name = Name; this. greenlight = greenlight;} public void gothrough () {console. writeline (string. format ("{0} comrade, {1}, please move forward. ", name, Greenlight. notice ));}}
Finally, call:
Public partial class run: FORM {public run () {initializecomponent ();} private void btnrun_click (Object sender, eventargs e) {trafficlight = new trafficlight (); driver driverone = new driver ("zhangsan", trafficlight); driver drivertwo = new driver ("Li Si", trafficlight); pedestrian pedestrianone = new pedestrian ("Wang Wu", trafficlight ); pedestrian pedestriantwo = new pedestrian ("Ma ", trafficlight); trafficlight. notices + = new observer. eventhandler (driverone. goleft); trafficlight. notices + = new observer. eventhandler (drivertwo. goleft); trafficlight. notices + = new observer. eventhandler (pedestrianone. gothrough); trafficlight. notices + = new observer. eventhandler (pedestriantwo. gothrough); trafficlight. notice = "the green light is on. "; trafficlight. turnon ();}}
Select console application for outputProgram:
The result is as follows:
Results and key points of implementation
1. Using object-oriented abstraction, the observer mode allows us to change the object and observer independently, so that the dependency between the two can be loosely coupled.
2. When the target sends a notification, no observer is required. The notification (which can carry the notification information as a parameter) will be automatically transmitted. The observer determines whether to subscribe to notifications. The target object knows nothing about this.
3. Event in C. The delegate acts as the abstract observer interface, while the object that provides the event acts as the target object. The delegate is more loosely coupled than the abstract observer interface.
4. the abstract subject role discloses its own events and can subscribe to any observer.
5. the abstract observer role defines a unified processing behavior. If the event-proxy mode is used in C #, the unified processing behavior is not so important. Sometimes, flexibility is limited. This example does not benefit from this interface for special reasons.
6. The operations that respond to methods to subscribe to proxy events can be defined in the observer or in the external definition. They are more flexible to put in the external definition according to their own needs.
7. The specific observer usually only needs to implement the response method.
8. You can have multiple subject roles and multiple observer roles. You can also set one role to two roles. The subject can also provide multiple events. In terms of applications, the observer pattern changes a lot.
Applicability
1. When an abstract model has two aspects, one of which depends on the other. Encapsulate the two in independent objects so that they can be changed and reused independently.
2. When changing an object, you need to change other objects at the same time without knowing how many objects need to be changed.
3. When an object must notify other objects, it cannot assume who the other objects are. In other words, you do not want these objects to be tightly coupled.
4. The behavior of one object triggers the behavior of multiple other objects. The former becomes the subject, and the latter is called the observer.
5. In order to reduce coupling, the subject does not want to directly call the observer method, but dynamically subscribe to the subject event for automatic chained response.
6. To increase flexibility, You can dynamically adjust the observer who subscribes to the subject event, or dynamically adjust the observer to subscribe to the subject event.
Advantages
1. The observer mode establishes an abstract coupling between the observer and the observer. What the observer role knows is that a specific observer aggregates, and each specific observer conforms to an abstract observer interface. The observer does not know any specific observer, but only knows that they all have a common interface. Since the observer and observer are not closely coupled, they can belong to different abstract layers.
2. The observer mode supports broadcast communication. The observer sends a notification to all registered observers.
Disadvantages
1. if an object to be observed has many direct and indirect observers, it takes a lot of time to notify all the observers.
2. If there is a circular dependency between the observer, the observer will trigger a circular call between them, resulting in system crash. Pay special attention to this when using the observation test mode.
3. If the notification to the observer is asynchronously delivered through another thread, the system must ensure that the delivery is carried out in the correct way.
4. Although the observer mode can enable the observer to know that the observed object has changed at any time, the observer mode does not have a mechanism to let the observer know how the observed object has changed.
Summary
1. In the observer mode, the notification dependency between one-to-multiple objects is loose, the maintainability and scalability of the program are greatly improved, and the open-closed principle is well met.
2. Due to this flexibility, when the observer subscribes to an event, should he consider whether there will be any destructive behavior? Will there be infinite loops or deadlocks? Will the observer affect other observers in response?
3. It is not suitable to use the observer mode when there are many observers, which may cause performance problems.
4. The traditional observer mode can be considered when the event-proxy mode is not used to complete the observer mode (for example, cross-network applications.