The observer mode is implemented in Java through the OBServable class and the OBServer interface. An OBServer object monitors a change in OBSERVABLE object. When the OBSERVABLE object changes, Observer is notified to do appropriate work. For example, in the document / view structure, the document is modified, and the view will be notified.
There are two ways in java.util.observable for Observer, one is the setchange () method to set an internal flag indicate that the data changes; one is the NotifyObservers () method to call all Observer in a list. The UPDATE () method notifies them that the data has changed.
Observer adds yourself to this list through the OBServable addOBServer () method. Although this list is owned by Observable, Observable does not know which Observer is observing waiting for notifications. Observable only provides a way to let Observer add yourself to list and ensure that Observer has changed. With this mechanism, there can be any Observer to observe OBSERVABLE without affecting the implementation of OBSERVABLE.
A simple example:
Import java.util.observable;
Public Class SimpleObserveRvable Extends Observable
{
Private int DATA = 0;
Public int getdata () {
Return Data;
}
Public void setdata (int i) {
IF (this.data! = i) {this.data = i; setChange ();
NotifyObservers ();
// Only after SetChange () is called, NotifyObservers () will call Update (), otherwise nothing.
}
}
}
Import java.util.observable;
Import java.util.observer;
Public Class SimpleObserver IMPLEments OBSERVER
{
Public SimpleObserver (SimpleObservable SO) {
So.addobServer (this);
}
Public void update (Observable O, Object Arg / * arbitrary object, used to pass parameters * /) {
System.out.println ("Data Has Changed To" O.Getdata ());
}
}
Public Class SimpleTest
{
Public static void main (String [] args) {
SimpleObservable Doc = New SimpleObserve ();
SimpleObserver View = New SimpleObserver (DOC);
Doc.setdata (1);
Doc.setdata (2);
Doc.setdata (2);
Doc.setdata (3);
}
}
Data Has Changed to 1
Data Has Changd to 2 // Second SetData (2) Due to no setchange, Update is not called
Data Has Changed to 3
The OBServable class has two private variables. A boolean type flag, setchange () set it true, only when it is true, the NotifyObservers method calls the OBServer's Update method. The other is a vector, saved all Observer lists to be notified, addObserver to the list, deleteobserver removes the specified OBServer, DELETEOBSERVERS Clear list, countobservers return to the number of Observer in the list, must be used before the OBServer object is destroyed DeleteObserver removes it from the list, or because there is still an object reference relationship, the OBServer object will not be collected by garbage, causing memory leaks, and the dead Observer will still be notified that it is possible to cause unexpected errors, and The list is getting bigger and bigger, and NotifyObservers will be more slower. All methods of Observable are synchronized, ensuring that there is no other thread when a thread is operated, and there is no other thread.
Observable's NotifyObserveRVERS (Object Obj) can pass the parameters into the UPDATE.
The leash will be added to the list of the list of notifications. Update will be called in turn, because a UPDATE is returned to the next update is called, so when there is a lot of operation in Update, it is best to get the work to another thread or Observer itself is also a Thread class, Observer hangs first. Since Update, there will be a hidden danger. The OBServer thread has not been hanged. Update is called, the notification message is missed, one solution is to implement a synchronized queue structure in Observer And there is a class to encapsulate parameters. Update implements a parameter class to encapsulate the parameters of the received notification message inside, then add it to the queue, the RUN method removes the parameter object from the queue, and processes, this It is guaranteed that there is no notification information is lost.
In multi-thread, only Observer will be different from single-threading, Observable does not need any changes to support multi-threaded because it makes a lot of OBServer as a separate thread.
A multi-thread example:
Import java.util. *;
Public Class SimpleObserverex Extends Thread Implements Observer
{
Queue Queue; // Use a message queue to receive Observable notifications, and ensure that the message will not be lost
Public void run () {
While (true) {
Argpack a = (argpack) queue.dequeue ();
Observable o = a.o;
Object obj = a.Arg;
// ... perform the corresponding work
}
}
Public Void Update (Observable O, Object Arg) {
Argpack A = New Argpack (O, Arg);
Queue.Queue (a);
}
}
Import java.util. *;
Public class queue extends linkedlist {
Public synchronized void queue (Object O) {
AddLast (O);
NOTIFY ();
}
Public synchronized void dequeue () {
While (this.isempty ()) {
Try {
Wait ();
}
Catch (InterruptedException EL) {
}
}
Object O;
Try {
o = this.RemoveFirst ();
}
Catch (nosuchelementexception) {
o = NULL;
}
Return O;
}
}
Public Class Argpack
{
Public Observable O;
Public Object Obj;
Public Argpack (Observable O, Object Obj) {
THIS.O = O; this.obj = Obj;
}
}
Observable is a class rather than an interface that limits its use, a solution is to put our package in an OBSERVABLE class (regarding our class instance as Observable domain), because the setchange in Observable is A protected method, we can't call it outside. So I can't pack an OBSERVABLE in our class, but if there is also a protected method in our class, then this approach cannot be used.