Design pattern (13): observer pattern

Posted by sevenmenkes on Wed, 17 Jun 2020 07:07:39 +0200

1. Definition

When there is a one to many mapping relationship between objects, in order to detect the change of an object, all objects that depend on the object can be notified in time to make changes in response. This mode is called observer mode.

2. Advantages

  • The observer and the observed are abstractly coupled without strong dependence.
  • A kind of mechanism of one touch is established, when the observed object changes, it can be found in time and modified accordingly.

3. Disadvantages

  • If an observed object has many direct and indirect observers, it will take a lot of time to notify all observers.
  • If there is a circular dependency between the observer and the observation target, the observation target will trigger a circular call between them, which may cause the system to crash.
  • There is no corresponding mechanism for the observer model to let the observer know how the observed object changes, but only know that the observed object has changed.

4. Use scenario

  • An abstract model has two aspects, one of which depends on the other. Encapsulate these aspects in separate objects so that they can be changed and reused independently.
  • The change of one object will lead to the change of one or more other objects. Without knowing how many objects will change, the coupling between objects can be reduced.
  • An object must notify other objects without knowing who they are.
  • You need to create A trigger chain in the system. The behavior of object A will affect object B, and the behavior of object B will affect Object C , you can use the observer pattern to create A chain trigger mechanism.

5. Precautions

  • JAVA already has support classes for observer patterns.
  • Avoid circular references.
  • If it is executed in sequence, a certain observer's error will cause the system to jam, which is generally asynchronous.  

6. Implementation

The observer pattern uses three classes: subject, observer, and Client. The subject object has methods to bind and unbind observers to and from the Client object. We create the Subject class, the Observer abstract class and the entity class that extends the abstract class Observer.

Observer patterndemo, our demonstration class uses Subject and entity class objects to demonstrate observer pattern.

6.1. Create the Subject class

/**
 * desc: Observed object
 *
 * @author xuebin3765@163.com
 * @version 1.0
 * @date 2020/06/17 11:11
 */
public class Subject {
	// Observer list
	private List<Observer> observers = new ArrayList<>();

	private int state;

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
		// Notify the observer that the object has changed
		notifyAllObservers();
	}

	/**
	 * Add observer objects to the observer list;
	 * @param observer Observer
	 */
	public void attach(Observer observer){
		observers.add(observer);
	}

	/**
	 * Notify all observers
	 */
	public void notifyAllObservers(){
		for (Observer observer : observers) {
			observer.update();
		}
	}
}

6.2 create observer abstract class

/**
 * desc: Abstract observer object class
 *
 * @author xuebin3765@163.com
 * @version 1.0
 * @date 2020/06/17 11:12
 */
public abstract class Observer {
	// Objects observed
	protected Subject subject;

	/**
	 * Abstract update notification method
	 */
	public abstract void update();
}

6.3. Create observer implementation class

/**
 * desc: Observer implementation class
 *
 * @author xuebin3765@163.com
 * @version 1.0
 * @date 2020/06/17 11:14
 */
public class BinaryObserver extends Observer{

	private Subject subject;

	public BinaryObserver(Subject subject) {
		this.subject = subject;
		subject.attach(this);
	}

	@Override
	public void update() {
		System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) );
	}
}
/**
 * desc:
 *
 * @author xuebin3765@163.com
 * @version 1.0
 * @date 2020/06/17 11:27
 */
public class HexaObserver extends Observer {

	private Subject subject;

	public HexaObserver(Subject subject) {
		this.subject = subject;
		subject.attach(this);
	}

	@Override
	public void update() {
		System.out.println( "Hexa String: " + Integer.toHexString( subject.getState() ) );
	}
}
/**
 * desc:
 *
 * @author xuebin3765@163.com
 * @version 1.0
 * @date 2020/06/17 11:27
 */
public class OctalObserver extends Observer {

	private Subject subject;

	public OctalObserver(Subject subject) {
		this.subject = subject;
		subject.attach(this);
	}

	@Override
	public void update() {
		System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) );
	}
}

6.4 test

/**
 * desc:
 *
 * @author xuebin3765@163.com
 * @version 1.0
 * @date 2020/06/17 11:28
 */
public class ObserverPatternDemo {
	public static void main(String[] args) {
		Subject subject = new Subject();

		new BinaryObserver(subject);
		new OctalObserver(subject);
		new HexaObserver(subject);

		System.out.println("First state change: 15");
		subject.setState(15);
		System.out.println("Second state change: 10");
		subject.setState(10);
	}
}

6.5 operation results

First state change: 15
Binary String: 1111
Octal String: 17
Hexa String: f
Second state change: 10
Binary String: 1010
Octal String: 12
Hexa String: a

Topics: Java