I introduce
Observer Pattern is a behavioral pattern. The one to many dependency between objects is defined to allow multiple observers to listen to a topic object at the same time. Similar to the broadcast mechanism, it only needs to distribute the broadcast, and the interested objects automatically receive the broadcast. What we usually call observer, Listener, Hook and Callback are all related to this mode
II Scene constraints
When a child cries, he will notify his father and his mother, who will take different actions
III UML class diagram
Version one
Version 2
The new event class decouples the observer from the topic. The observer can perform different operations according to different events or directly operate the event source
IV Schematic code (version 1)
Business code
//Abstract observer public interface Observer { void action(); } //Abstract theme abstract class Subject{ protected List<Observer> observers = new ArrayList<>(); public void addObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } public abstract void notifyObserver(); } //Specific subject - observed class Baby extends Subject{ @Override public void notifyObserver() { System.out.println("baby cry"); observers.forEach(Observer::action); } } //Specific observer class Dad implements Observer { @Override public void action() { System.out.println("dad feed baby"); } } //Specific observer class Mum implements Observer { @Override public void action() { System.out.println("mum hug baby"); } }
client
public class Client { public static void main(String[] args) { Baby baby = new Baby(); baby.addObserver(new Mum()); baby.addObserver(new Dad()); baby.notifyObserver(); } }
V Schematic code (version 2)
//Abstract observer public interface Observer { void action(Event event); } //Abstract theme abstract class Subject { protected List<Observer> observers = new ArrayList<>(); public void addObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } public abstract void notifyObserver(); } //Specific subject - observed class Baby extends Subject { @Override public void notifyObserver() { System.out.println("baby cry"); CryEvent cryEvent = new CryEvent(new Date().getTime(), this); observers.forEach(observer -> observer.action(cryEvent)); } } //Abstract event abstract class Event { public abstract Object getSource(); } //Specific events class CryEvent extends Event { public long when; Baby source; public CryEvent(long when, Baby source) { this.when = when; this.source = source; } @Override public Baby getSource() { return source; } } //Specific observer class Dad implements Observer { @Override public void action(Event event) { System.out.println("dad feed baby"); if(event.getSource() instanceof Baby){ System.out.println("dad Process the event source"); } } } //Specific observer class Mum implements Observer { @Override public void action(Event event) { System.out.println("mum hug baby"); if(event.getSource() instanceof Baby){ System.out.println("mum Process the event source"); } } }
client
public class Client { public static void main(String[] args) { Baby baby = new Baby(); baby.addObserver(new Dad()); baby.addObserver(new Mum()); baby.notifyObserver(); } }
Vi Observer mode and publish subscribe mode
Publish subscribe mode
- Publishers do not notify subscribers directly
- Publishers and subscribers are completely decoupled
Observer mode
- The subject should notify the observer by itself
- Loose coupling between subject and observer
VII advantage
- Comply with the dependency inversion principle (both observers and topics rely on abstraction)
- Reduce coupling (coupling between subject and observer)
VIII Typical application in JDK
In Java There are many observer patterns under the AWT package. Let's take a look at the simple UML class diagram first
Topic role: component class provided by java (take Button as an example)
Observer role: event listener provided by java (various listeners)
Event roles: mouse events, keyboard events, and so on
Let's take a look at a small demo
Add a button in the window, add mouse and keyboard related events to the button, and print corresponding statements on the console when clicking the button or pressing the keyboard
public class MainFrame extends JFrame { public MainFrame() throws HeadlessException { //Define a specific topic Button button = new Button("click"); //Add an observer to the topic (mouse listening) button.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { //MouseEvent is a specific event System.out.println("The button is clicked"); } }); //Add an observer to the topic (keyboard monitor) button.addKeyListener(new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { //KeyEvent is a specific event System.out.println("Press" + e.getKeyChar()); } }); add(button); setSize(100,100); this.setLocationRelativeTo(null); this.setVisible(true); } public static void main(String[] args) { new MainFrame(); } }
The KeyAdapter and MouseAdapter here use Adapter mode