The observer mode is one of the software design modes and is also commonly used, especially in GUI programming. There are many articles about design patterns written on the Internet, and many articles are well written. Although there is a suspicion of repeating the early wheel, this wheel is not the other wheel, with different focus, different ideas, and different ways of telling it.
Key Elements
theme:
A topic is the object observed by the observer. A topic must have the following three characteristics.
Observer:
When the subject changes, receiving notifications for specific processing is a feature that the observer must have.
Why use this mode
Here is an example to illustrate that the milk delivery station is the theme. The milk subscription customer is the monitor. After the customer subscribes to the milk from the milk delivery station, he will receive the milk every day. If the customer does not want to subscribe, he can cancel and he will not receive milk in the future.
Loose coupling
The observer adds or deletes code without modifying the topic, just call the corresponding method of adding or deleting the topic.
The subject is only responsible for notifying the observer, but does not need to know how the observer deals with the notification. For example, the milk delivery station is only responsible for delivering milk and does not care whether the customer drinks it or washes his face.
The observer just needs to wait for the topic notification, without observing the details related to the topic. As for the same example, customers only need to care about the milk delivery station to deliver the milk, not about which courier is from or what kind of transportation to deliver the milk.
Java implements observer mode
1. Java's own implementation
Class diagram
/** * The observation target inherits from java.util.Observable * @author stone * */ public class UpdateObservable extends Observable { private int data; public UpdateObservable(Observer observer) { addObserver(observer); /* * add other observer */ } public int getData() { return data; } public void setData(int data) { if (data != this.data) { this.data = data; setChanged(); //Tag changes, NotifyObservers(); //Notification} } @Override public synchronized void addObserver(Observer o) { super.addObserver(o); } @Override public synchronized void deleteObserver(Observer o) { super.deleteObserver(o); } @Override public void notifyObservers() { super.notifyObservers(); } @Override public void notifyObservers(Object arg) { super.notifyObservers(arg); } @Override public synchronized void deleteObservers() { super.deleteObservers(); } @Override protected synchronized void setChanged() { super.setChanged(); } @Override protected synchronized void clearChanged() { super.clearChanged(); } @Override public synchronized boolean hasChanged() { return super.hasChanged(); } @Override public synchronized int countObservers() { return super.countObservers(); } } /** * Observer implements java.util.Observer interface* @author stone * */ public class UpdateObserver implements Observer { @Override public void update(Observable o, Object arg) { System.out.println("Received notification of data change:"); if (o instanceof UpdateObservable) { UpdateObservable uo = (UpdateObservable) o; System.out.print("Data changed to:" + uo.getData()); } } } 2. Custom observation model
Class diagram
/** * Abstract Observer * Observation update* @author stone * */ public interface IWatcher { /* * Notification interface: * 1. Simple notification* 2. The observer needs data of the change of the target, so the target can be used as a parameter, see Java's Observer and Observable */ // void update(IWatched watched); void update(); } /** * Abstract target Subject * Provides an interface to register and delete observer objects, and an interface to notify observers to observe* and the interface to which the target is observed* @author stone * */ public interface IWatchedSubject { public void add(IWatcher watch); public void remove(IWatcher watch); public void notifyWhatchers(); public void update();//Interface to the observed business changes} /** * Specific observer Concrete Observer * * @author stone * */ public class UpdateWatcher implements IWatcher { @Override public void update() { System.out.println(this + "Observed: the target has been updated"); } } /** * Specific target role Concrete Subject * @author stone * */ public class UpdateWatchedSubject implements IWatchedSubject { private List<IWatcher> list; public UpdateWatchedSubject() { this.list = new ArrayList<IWatcher>(); } @Override public void add(IWatcher watch) { this.list.add(watch); } @Override public void remove(IWatcher watch) { this.list.remove(watch); } @Override public void notifyWhatchers() { for (IWatcher watcher : list) { watcher.update(); } } @Override public void update() { System.out.println("Target update......"); notifyWhatchers(); } } A listener is an implementation of the observer:
Class diagram
/** * Listener after registering* @author stone * */ public interface IRegisterListener { void onRegistered(); } /** * Listener When the user logs in* @author stone * */ public interface ILoginListener { void onLogined(); } /* * Listener is an implementation of the observer mode* Add listeners to some business interfaces that require listening, call the corresponding methods of the listener to implement listening*/ public class User { public void register(IRegisterListener register) { /* * do ... register */ System.out.println("Registering..."); //After registration register.onRegistered(); } public void login(ILoginListener login) { /* * do ... login */ System.out.println("Registering..."); //After login.onLogined(); } } /** * Observer mode behavioral pattern* The observer mode defines a one-to-many dependency, allowing multiple observer objects to observe a target object at the same time. * When this target object changes in its state, it will notify all observer objects, so that they can automatically update themselves. The target object needs an interface to add, remove, and notify observers* * @author stone */ public class Test { public static void main(String[] args) { /* * Use Java's own Observer interface and Observable class*/ UpdateObservable observable = new UpdateObservable(new UpdateObserver()); observable.setData(99); System.out.println(""); System.out.println(""); /* * Custom observer model*/ IWatchedSubject watched = new UpdateWatchedSubject(); watched.add(new UpdateWatcher()); watched.add(new UpdateWatcher()); watched.update(); System.out.println(""); /* * Sub-mode-listener*/ User user = new User(); user.register(new IRegisterListener() { @Override public void onRegistered() { System.out.println("After listening to registration..."); } }); user.login(new ILoginListener() { @Override public void onLogined() { System.out.println("After listening to login..."); } }); } }Received notification of data change: Data changed to: 99 The target is being updated... Observer.UpdateWatcher@457471e0 Observed: The target has been updated observer.UpdateWatcher@5fe04cbf Observed: The target has been updated and is registering... After listening to registration. . . Logging in... After listening to login. . .