Observer mode (Observer pattern) (i): An introduction to the Observer model

Source: Internet
Author: User
I. Intention


Defines a one-to-many dependency between objects, and when the state of an object changes, all objects that depend on it are notified and automatically updated.



Second, applicability


The design pattern mentions that observer mode can be used in any of the following situations:


1. When an abstract model has two aspects, one aspect relies on the other. Encapsulate the two in separate objects so that they can be changed and reused independently of each other.


2. When a change to an object needs to change other objects at the same time, it is not known exactly how many objects are to be changed.


3. When an object must notify other objects, it cannot assume that other objects are. In other words, you don't want these objects to be tightly coupled.



Three, composition


--Abstract theme (Subject) role

All references to the Observer object are saved in a collection, and each abstract theme role can have any number of observers. Abstract topics provide an interface to add and remove observers. Abstract theme roles are typically implemented using interfaces or abstract classes.


--abstract observer (OBSERVER) role

Define an update interface for specific observers and update themselves when they are notified of the subject.


--specific theme (concrete Subject) role

Notify all registered observers of changes in the internal state of the specific subject. is a subclass (or implementation) of an abstract theme.


--specific observer (concrete Observer) role

The role implements the update interface required by the abstract observer role so that its state is compatible with the state of the subject. If necessary, the specific observer role can hold a reference to a specific theme role.



IV. Structure


The above subject and observer can be implemented in Java interface or abstract class, where "interface" in design mode does not necessarily refer to interface in Java (or other languages).

Sometimes we may not need to add the state attribute of the record itself to the subject or observer, and perhaps there is no need for the observer to hold a reference to the subject of the subject type. The focus of the observer pattern is to use interfaces or abstract classes to implement loose coupling of specific subjects with specific observers, and to update all of its observers by maintaining a set of observer types and by implementing a one-to-many dependency of the observer, adding a theme to delete an observer, and updating the subject.



v. Realization


1. The simplest implementation


This simple implementation does not include the attributes of the state of the record itself in the subject and the observer. Also, there is no reference to the subject in the observer, but the basic features of the observer pattern are realized, which can be extended according to its own needs (e.g., join status or reference to the subject, etc.).


(1) Abstract theme roles

Public interface Subject
{public
	void Registerobserver (Observer o);

	public void Removeobserver (Observer o);

	public void Notifyobservers ();
}

Use interfaces instead of abstract classes to implement abstract topics here, because Java (or C #, and so on) is a single inheritance, when we use abstract classes to implement abstract topics, it is a dilemma for a class that wants to have subject behavior while trying to have another superclass.


(2) Specific theme roles

public class ConcreteSubject implements Subject
{
	list<observer> observers = new Arraylist<observer > ();
	
	@Override public
	void Registerobserver (Observer o)
	{
		if (o = = null)
			throw new NullPointerException (); C7/>if (!observers.contains (o))
		{
			observers.add (o);
		}
	}

	@Override public
	void Removeobserver (Observer o)
	{
		observers.remove (o);

	}

	@Override public
	void Notifyobservers ()
	{for
		(Observer o:observers)
			o.update ();
	}

(3) abstract observer role

Public interface Observer
{public
	void Update ();
}


(4) Specific observer roles

public class Concreteobserver implements Observer
{
	@Override public
	Void Update ()
	{
	  // Add hashcode to distinguish different objects
      System.out.println (This.hashcode () + "  says:i ' m notified!");
	}


(5) Client testing:

public class Client
{public
	static void Main (string[] args)
	{
		Subject Subject = new ConcreteSubject (); C4/>observer O1 = new Concreteobserver ();
		Observer O2 = new Concreteobserver ();
		Observer O3 = new Concreteobserver ();

		Subject.registerobserver (O1);
		Subject.registerobserver (O2);
		Subject.registerobserver (O3);
		Subject.registerobserver (O1)//test Duplicate Registration

		subject.notifyobservers ();
	}


2. Enhancements: Add theme status and save references to topics in the viewer


(1). Abstract Theme Roles

Public abstract class Subject
{
	private list<observer> observers = new arraylist<observer> ();

	public void Registerobserver (Observer o)
	{
		if (o = = null)
			throw new NullPointerException ();
		Avoid registering the same observer multiple times
		if (!observers.contains (o))
		{
			observers.add (o)}
	}

	public void Removeobserver (Observer o)
	{
		observers.remove (o);
	}

	public void Notifyobservers ()
	{for
		(Observer o:observers)
		{
			o.update ()
}}}

This is the abstract theme role of the abstract class implementation, because Registerobserver, Removeobserver, notifyobservers are common parts of all subclasses, and it is natural to implement them in the superclass, and you can reuse the code of the parent class. Subclasses can implement specific topics more concisely. But for a single inherited language like Java, there is a dilemma that we've talked about before.


(2). Abstract Observer role

Public interface Observer
{public
	void Update ();
}

The interface is still used to implement the abstract observer role, the subject and the observer's loose coupling is embodied here, for Java and other single inherited languages, the implementation of abstract observers, the use of interfaces than the use of abstract classes.


(3). Specific Theme Roles

public class ConcreteSubject extends Subject
{
	Object state;//the state of the specific subject itself public
	
	Object getState ()
	{ return state
		;
	}

	public void SetState (Object state)
	{
		this.state = state;
	}
}

(4) Specific observer roles

public class Concreteobserver implements Observer
{
	//specific observer internally maintains a concretesubject type of reference
	to a specific subject ConcreteSubject subject;
	Object State;

	Public Concreteobserver (concretesubject subject)
	{
               if (SUBJECT==NULL)//observer cannot listen for null        throw New NullPointerException ();
                This.subject = subject;
		This.subject.registerObserver (this);
	}
        Unbind the subject (registration) public
	Void Unregister ()
	{
		this.subject.removeObserver (this);
	}

	@Override public
	Void Update ()
	{state
		= This.subject.getState ();
		Hashcode is used to distinguish different observer
		System.out.println (This.hashcode () + "I ' m notified!!");
	}

The specific observer here contains a reference to the type of subject that is ConcreteSubject type, and we want it to be subject type, Because of this we can use polymorphism to let a specific observer first remove the registration of the original topic (because it maintains only one subject reference instead of multiple) and then register to different types of specific topics. But here, it's hard to do because state information is all about specific topics, and different specific topics have different state information. This design conforms to the description in the above structure diagram, this is also described in the structure diagram in the classic book of design patterns, and I think the loose coupling of the observer pattern is reflected in the following: All observers implement the observer interface so that the subject does not have to know the specific observer class, just call its update () method on the line.

Here, a little further modification may be possible (this modification may not change the original situation):

Changing the hold of a subject reference in a specific observer to the subject type, while using ConcreteSubject for type judgments and coercion of type conversions (seemingly adding a lot of if statements), is done in the Weather Report board example in the headfirst design pattern. See the headfirst in the implementation of the meteorological station in the class diagram or specific observer.

There is also a way in which we synchronize the subject and the observer's State with the following: "states = This.subject.getState ();", which is called "pull" data, i.e., the observer obtains the data from the subject according to his own needs. However, perhaps the "push" data is better, with the status of the subject being passed to the observer via Update (state) (Whether you use it or not, to give you the data), as well, as in the Weather Report board example in headfirst design mode. See the class diagram or specific observer in the implementation of the weather station in headfirst, the Java built-in support for the Observer pattern also offers two options: Push or pull, see the following: Java's built-in support for observer mode.


(5) test

public class Client
{public
	static void Main (string[] args)
	{
		ConcreteSubject concretesubject = new ConcreteSubject ();
		Concreteobserver O1 = new Concreteobserver (concretesubject);
		Concreteobserver O2 = new Concreteobserver (concretesubject);

		Concretesubject.notifyobservers ();
		O1.unregister ();
		O2.unregister ();
		Concretesubject.notifyobservers ();
	}




VI. built-in support for observer mode in Java


The Java.util.Observable class acts as an abstract theme role in the Observer pattern (it can be called "observable" here)

The Java.util.Observer interface acts as an abstract observer role in the Observer pattern (which embodies "loose coupling")

The Java built-in support structure for the Observer pattern is:



the inadequacy of the place (excerpt from Headfirst): Java.util.Observable is an abstract class, as we mentioned earlier, because Java is a single inheritance, which makes it impossible for a class to have both observable and other superclass behavior, which limits the observable reuse potential (which is also in the code Implement the reason for using interface in 1). In addition, observable sets critical methods such as setchanged () to protected, which means that you cannot create observable instances and combine them into your own objects unless you inherit the observable class, which violates the "multiple-use combination, The principle of using less inheritance.

(An example: "Using Java built in support to implement the Headfirst weather station")



Vii. push and pull data


Push data refers to a theme that passes the status information (data) as a parameter to a specific observer through the update (state) method (defined in the Observer Interface), which is then updated using the information that is useful in parameter state as needed.


The "pull" data refers to the fact that the observer extracts the data he needs from the subject as needed.


In Java's built-in support for the observer pattern, the way in which these two states (data) are delivered is also provided:


There is and only one method in the Java.util.Observer interface (that is, the abstract observer role): Void update (Observable o, Object arg), where parameter arg passes the state information of the subject (observable).


The Java.util.Observable class (observable, that is, our "abstract theme Role") method Notifyobservers () is the support for "pull" data, method Notifyobservers (Object Arg) is the "push" Data support.



viii. principles of design


Design principles: For the interaction between the loosely coupled design efforts.


In the Observer pattern, changing the subject or the observer is not affecting the other because the two are loosely coupled, so as long as the interface between them is kept, we are free to change them.
Loosely coupled design allows us to build resilient OO systems that can cope with change because the interdependence between objects is minimized.



IX, other


1. The above topic and State of the Observer (data) State refers to the status information in the subject (or observer), which can be a set of data, not just a state data of type object.


2. Appropriate implementation of the observer pattern according to its own needs, such as the implementation of an abstract theme (interface or abstract class). Whether to include a property in the subject or observer that represents its state, or whether to include a reference to the subject type in the Observer (the type of the reference is of an abstract subject type or a specific subject type.) and choose how to pass the data (push or pull). and whether or not to use a similar observable setchanged () method to properly adjust the subject to inform the observer of the extent of the notice or to a certain degree of notice or ...? Wait


3. For the more complex dependency of the Observer model, "design pattern" is described in the following excerpt


Encapsulates complex update semantics:

When the dependencies between the target and the observer are particularly complex, you may need an object to maintain these relationships. We call such an object the change manager (Changemanager). It aims to minimize the amount of work required by the observer to reflect changes in the state of its objectives. For example, if an operation involves making changes to several interdependent targets, it is important to ensure that only once all the targets have been changed are they notified to their observers at once, rather than each target notifying the observer.

Changemanager has three responsibilities:

A It maps a target to its observer and provides an interface to maintain the mapping. This does not require a target to maintain a reference to its observer, or vice versa.
b It defines a specific update policy.
(c) In response to a request for a goal, it updates all observers who are dependent on this goal.

The block diagram on the next page describes a simple implementation of the observer pattern based on Changemanager. There are two kinds of special changemanager. Simplechangemanager always updates all the observers for each goal, which is relatively simple. On the contrary, the Dagchangemanager process of the object and the dependencies of the Observer is composed of a loop-free direction graph. When an observer observes multiple targets, Dagchangemanager is better than Simplechangemanager. In this case, the changes that occur in two or more targets may result in redundant updates. Dagchangemanager ensure that the observer receives only one update. Of course, Simplechangemanager is better when there is no problem with multiple updates. Changemanager is an instance of a mediator (mediator) pattern. There is usually only one changemanager, and it is globally visible. Here the Singleton (single example) pattern may be useful.


Reprint please indicate the source: http://blog.csdn.net/jialinqiang/article/details/8871965

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.