Observer mode, also known as Publish/Subscribe (Publish/Subscribe) mode, defines a one-to-many dependency, allowing multiple observer objects to listen to a topic object at the same time. This subject object notifies all observer objects when the state changes, so that they can automatically update themselves. There is a bad side effect of splitting a system into a series of collaborative classes, which is the need to maintain consistency between related objects. We do not want to tightly couple all kinds of things to maintain consistency, which will cause inconvenience to maintenance, expansion and reuse. What the observer model does is actually to decouple, so that both parties to the coupling rely on abstraction rather than concrete.
The observer model is a model that is widely used in practice. Its application scenarios include a factory that produces rice and n merchants selling rice. N merchants first register their own contact information in this factory. After the factory produces a certain amount of rice, they will notify the n merchants to pick up the goods according to the contact information. In this example, registration (attach) and notification (notify) in the observer mode are used, that is, when the notifier's status changes, each observer is notified in turn.
Subject is an abstract notificationer, and Observer is an abstract observer. If the derived class you are creating is an object that is not related to, you can consider using the interface to implement several identical methods.
The Java code is as follows:
abstract class Subject { private ArrayList<Observer> observersList = new ArrayList<Observer>(); // add observers public void Attach(Observer ob) { observersList.add(ob); } // remove observers public void Detach(Observer ob) { observersList.remove(ob); } public void Notify() { for (Observer ob: observersList) { ob.Update(); } }}abstract class Observer { public abstract void Update();}public class ConcreteObserver extends Observer { private String name; private String observerStatus; private ConcreteSubject subject; public ConcreteObserver(ConcreteSubject subject, String name) { this.subject = subject; this.name = name; } public void Update() { observerStatus = subject.getSubjectStatus(); } }public class ConcreteSubject extends Subject { private String subjectStatus; public String getSubjectStatus() { return subjectStatus; } public void setSubjectStatus(String subjectStatus) { this.subjectStatus = subjectStatus; } public static void main(String[] args) { // TODO Auto-generated method stub ConcreteSubject s = new ConcreteSubject(); s.Attach(new ConcreteObserver(s, "X")); s.Attach(new ConcreteObserver(s, "Y")); s.Attach(new ConcreteObserver(s, "Z")); s.setSubjectStatus("Ready"); s.Notify(); }}In the above code, there are abstract observers and abstract notifiers. When the state of the Subject changes, the call function can notify the observer registered inside it. This design idea is also common in daily life, such as the rice producers and rice sellers mentioned at the beginning. Another application scenario is, for example, if a book in the bookstore is out of stock and the customer still wants to buy it, he can register. After the goods arrive, the bookstore owner will call to notify the customer who wants to buy the book in turn. This registration mechanism is also reflected in other programming techniques. For example, a program registers multiple callback functions with the underlying library. When the conditions are met, the underlying library will notify (or call) the callback function provided by the upper layer.
The above code is written in Java, and it is similar in C++. It mainly uses Subject to save the Observer pointer. However, C++ should consider the issue of freeing memory. Note that when Observer itself is to be destroyed, the Subject's Detach function must be called, otherwise the problem of using wild pointers may cause crash during Update. Consider using Subject to manage the life cycle of Observer.