Reprint: http://www.cnblogs.com/zuoxiaolong/p/pattern7.html
In this chapter we discuss a design pattern, the observer pattern, that may be used in a Web project, in addition to the previous singleton and proxy mode.
Speaking of the observer mode, LZ is very excited, originally this is the first to let the LZ feel the design of a powerful guy. The LZ to do a small Web project, to the server file, a requirement is to display the upload progress, LZ is to use this mode to solve the problem at that time, LZ contact Java just a few months, BISHI with the Observer mode.
Now, when it comes to observer patterns, there is a relatively large number of places to use, and in general it is possible to use the observer pattern if a change in the state of an object requires notifying a number of objects of interest to the object.
The following LZ first give the Observer mode standard version of the definition, quoted from Baidu Encyclopedia.
definition: The Observer pattern (sometimes referred to as the publish-subscribe pattern, model-view mode, source-listener mode, or slave mode) is one of the software design patterns. In this mode, a target object manages all the observer objects that are dependent on it and proactively notifies when its own state changes. This is usually done by calling the methods provided by each observer. This pattern is often used to implement event handling systems.
In the definition above, there are several main meanings, first of all objects with a target, the popular point is a class, it manages all dependent on its observer object, or the popular point is the Observer class, and in its own state changes, the initiative to give notice.
in simple terms, it is a class that manages all of the observer classes that depend on it, and it proactively notifies those classes that depend on it when the state changes.
Then we give the above description of the observer pattern of the class diagram, Baidu Encyclopedia does not give the observer pattern of the class diagram, where the LZ own use of tools to draw one for you.
As you can see, our Observer class observable only associates a list of observer and then notifies these observer with the Notifyobservers method when their state changes, and what exactly these observer are, The observer does not care or need to know.
The coupling between the observer and the observer is reduced to a very low level, and our specific observer must know who we are observing, so it depends on the person being observed.
Below the LZ to write a very simple observer pattern, to use Java code to simply explain the above class diagram.
The first is the Observer interface.
Package net;//This interface is intended to provide a uniform observer for the method of making the corresponding behavior public interface Observer { void update (Observable o); }
The other is the specific observer.
Package Net;public class ConcreteObserver1 implements observer{public void update (Observable o) { SYSTEM.OUT.PRINTLN ("Observer 1 observed" + O.getclass (). Getsimplename () + "changed"); System.out.println ("Viewer 1 makes the corresponding");} }
Package Net;public class ConcreteObserver2 implements observer{public void update (Observable o) { SYSTEM.OUT.PRINTLN ("Observer 2 observed" + O.getclass (). Getsimplename () + "changed"); System.out.println ("Viewer 2 makes the corresponding");} }
Here is the observer, it has a list of observers, and there is a way to notify all observers, and the way to notify them is to call the observer's generic interface behavior Update method. Let's look at its code.
Package Net;import Java.util.arraylist;import Java.util.list;public class Observable { list<observer> Observers = new arraylist<observer> (); public void Addobserver (Observer o) { observers.add (o); } public void Changed () { System.out.println ("I am the Observer, I have changed"); Notifyobservers ();//Notify all observers of their own } public void Notifyobservers () {for (Observer observer:observers) { C11/>observer.update (this);}}}
Here is a simple, two new methods, one is to change their own and notify the observers, one is to give the client a public interface to add observers.
Let's use the client to call and see how the client operates.
Package Net;public class Client {public static void Main (string[] args) throws Exception { Observable Observable = new Observable (); Observable.addobserver (New ConcreteObserver1 ()); Observable.addobserver (New ConcreteObserver2 ()); Observable.changed (); }}
The results of the operation are as follows.
We can see that when we manipulate the observed, the observer will make the corresponding action as long as the changed method is called, and the Observer is the preparation stage, and the specific observer is connected to the observer.
The following LZ gives a practical example, for example, we often look at the novel Web site, has such a function, that is, readers can subscribe to the author, there are obvious observer pattern cases, is the author and the reader. Their relationship is that once the reader pays attention to an author, the author should inform the reader of any new book, which is obviously a case of the observer pattern, so we can use the observer pattern to solve it.
Since the ready-made observer interface and the Observer class have been written for the convenience of the developer in the JDK, the LZ first gives the out-of-the-box observer and the Observer Code in the JDK, plus a little explanation, to help some readers familiarize themselves with the support for the observer pattern in the JDK.
First come to the Observer interface.
Observer interface, each observer must implement this interface public interface Observer { //This method is the response action that the observer makes when observing the object's changes, from which the observed object and a reserved parameter void are passed Update (Observable o, Object arg);}
The following is the class of the observer.
Import java.util.vector;//is the Observer class public class Observable {//This is a change identifier to mark whether the observed person has changed the private Boolean changed = FALSE; Holding a list of observers private Vector obs; Public Observable () {obs = new Vector (); }//Add observer, add will go to public synchronized void Addobserver (Observer o) {if (o = = null) throw new NULLP Ointerexception (); if (!obs.contains (o)) {obs.addelement (o); }}//delete observer public synchronized void Deleteobserver (Observer o) {obs.removeelement (o); The overloaded method of//notifyobservers (Object arg) public void Notifyobservers () {notifyobservers (null); }//Notify all observers that the observed person has changed and you can execute your Update method. public void Notifyobservers (Object arg) {//A temporary array, used for concurrent access to the observer, retains the current state of the Observer list, which is actually a design pattern, that is, the memo pattern. Object[] arrlocal; Note this synchronization block, which indicates that the object is locked when it gets the list of observers//that is, before I get to the Observer list, no other thread is allowed to change the Observer list synchronized (this) {///If no change is returned directly to I F (!changed) return; This places the current list of observers into a temporary array arrlocal = Obs.toarray (); Resets the change identity back to unchanged clearchanged (); }//Note that the For loop is not in the synchronization block, the lock of the Observer has been released at this time, and the other threads can change the Observer list//But this does not affect our current operation because we have copied the observer list to a temporary array//At the time of notification we only notify the array Observers, currently deleting and adding observers, will not affect our notified object for (int i = arrlocal.length-1; i>=0; i--) ((Observer) arrlocal[i]). Updat E (this, ARG); }//Delete all observers public synchronized void Deleteobservers () {obs.removeallelements (); }//Identity The Observer has been changed over protected synchronized void setchanged () {changed = TRUE; }//Identity The observer did not change protected synchronized void clearchanged () {changed = FALSE; }//Returns whether the observed person has changed public synchronized Boolean hasChanged () {return changed; }//Returns the number of observers public synchronized int Countobservers () {return obs.size (); }}
The observer, apart from a bit of synchronization, needs a special explanation, and the rest of you can see the purpose of each method. In fact, the above JDK class is vulnerable, or, when we use the observer pattern to pay attention to a problem, that is, notifyobservers this method of the code.
for (int i = arrlocal.length-1; i>=0; i--) ((Observer) arrlocal[i]). Update (this, ARG);
The JDK does not crawl the exception in the Update method when iterating through the observer, so if an update method throws an exception in the process, the remaining observers will not be notified. So the LZ personally confused the intention (LZ can not imagine the Java class library manufacturer did not consider this issue), is sun really forgot to consider this point, or other meaning? Of course, if you have their own views can inform the LZ, but LZ that, whether it is sun so do not have the intention, or really owe consideration, we have to pay attention to the Update method must deal with the exception, the individual feel that the practice of more insurance in the JDK is as follows.
for (int i = arrlocal.length-1; i>=0; i--) { try { (Observer) arrlocal[i]). Update (this, arg); } catch ( Throwable e) {e.printstacktrace ();} }
This way, regardless of whether any of the updates are successful or not, the rest of the observers are updated, and our own insurance is to add a try block to the Update method or to verify that no runtime exceptions occur.
Above LZ and you together to analyze the JDK mode of the source of the observer, below we take the example of the above-mentioned novel network, do a demo.
first to figure out who is observing who is between the reader and the author, it is obvious that the reader should be observing the author. So the author is the Observer, the reader is the Observer, in addition to these two classes, we also need to add an additional manager to help us manage the list of authors to facilitate the reader's attention, so a viewer mode of the demo appears. Below, the first is the reader class, LZ in each class has added a point comment.
//reader class, to implement the viewer interface public class reader implements observer{private String name; Public Reader (String name) {super (); THIS.name = name; } public String GetName () {return name; }//readers can focus on one author, and the attention represents adding themselves to the author's list of Observers public void subscribe (String writername) {writermanager.getinstance () . Getwriter (Writername). Addobserver (this); }//readers can cancel their attention to one author, and the cancellation of attention represents the deletion of the public void unsubscribe (String writername) {writermanager.getins) from the author's Observer list Tance (). Getwriter (Writername). Deleteobserver (this); }//When the interested author publishes a new novel, the reader will be notified to see the public void update (Observable o, Object obj) {if (o instanceof Writer) { Writer writer = (writer) o; System.out.println (name+ "Know" + writer.getname () + "published the new book" + Writer.getlastnovel () + ", do not want to see! "); } } }
The following is the author class.
Author class, to inherit from the Observer class public class writer extends observable{ private string name;//the name of the author of the private string lastnovel;// Record Author's latest published novel Public writer (String name) { super (); this.name = name; Writermanager.getinstance (). Add (this); } The author released a new novel, to inform all concerned about their readers public void Addnovel (String novel) { System.out.println (name + "released new book" + novel + ")! "); Lastnovel = novel; Setchanged (); Notifyobservers (); } Public String Getlastnovel () { return lastnovel; } Public String GetName () { return name; }}
Then we also need a manager to help us manage these authors. As follows.
Import Java.util.hashmap;import java.util.map;//Manager, maintain a unique list of authors public class writermanager{ private map< String, writer> writermap = new hashmap<string, writer> (); Add author public void Add (writer writer) { writermap.put (Writer.getname (), writer); } Get author public writer getwriter (String name) { return Writermap.get (name) according to author's name; } Singleton Private Writermanager () {} public static Writermanager getinstance () { return writermanagerinstance.instance; } private static class writermanagerinstance{ private static Writermanager instance = new Writermanager ();} }
OK, so our observer model is done, this simple demo can support the reader to focus on the author, when the author publishes the new book, the reader will observe this thing, will produce corresponding action. Let's write a client call.
//client calls public class client {public static void main (string[] args) {//assume four reads , two authors reader r1 = new Reader ("Xieguangkun"); Reader r2 = new Reader ("Zhao Si"); Reader R3 = new Reader ("Seven elder brother"); Reader r4 = new Reader ("Liu Can"); Writer W1 = new writer ("Xie Bigfoot"); Writer W2 = new writer ("Wangxiaomeng"); Four people focused on the R1.subscribe ("Xie Bigfoot"); R2.subscribe ("Xie Bigfoot"); R3.subscribe ("Xie Bigfoot"); R4.subscribe ("Xie Bigfoot"); Seven elder brother and Liu can also concerned about Wangxiaomeng R3.subscribe ("Wangxiaomeng"); R4.subscribe ("Wangxiaomeng"); The author publishes the new book and notifies the interested reader//Xiedajiao to write the design pattern w1.addnovel ("design mode"); Wangxiaomeng wrote the Java Programming idea W2.addnovel ("Java Programming idea"); Xieguangkun Cancel attention to R1.unsubscribe ("Xie Bigfoot"); The Xieguangkun W1.addnovel ("Observer Mode") will not be notified by the writing of the book. } }
Looking at the results we have, we will find that we do inform the reader of the dynamics of the author's concerns, and that the reader will not be notified of the author's dynamics after the readers have canceled their attention. The following is the result of the operation.
We use the Observer pattern for the purpose of informing the author that he is no longer concerned about his new book, and more importantly, that he does not need to be concerned about the reader or any other person, but that this person realizes the observer interface, that our observer relies on only an abstract interface observer interface, And do not care about the specific observer who is what, for example, if visitors can also focus on the author, so long as the visitor class to implement the Observer interface, then the same can be included in the author's Observer list.
In addition, we allow the reader to choose the object of his or her own attention, which is equivalent to the observer's function of maintaining the notification object to the observer, and the benefit is that an observer may have more than n observers, so it is difficult for the observer to maintain the list itself, as a teacher is known to many students, So is all the students remember the teacher's name is simple, or let the teacher remember the name of n more students simple? The answer is obvious, and it is easiest for students to remember the name of a teacher.
(vi) Observer pattern