76.JAVA programming Idea--observer paradigm
The Observer (Observer) paradigm solves a fairly common problem: how to fix a group of objects that need to be updated because the state of some objects has changed? This problem can be seen in the Model-View section of Smalltalk's MVC (model-View-controller), or in the almost equivalent document-view structure. Now we have some data ("documents") and multiple views, which are assumed to be a single graph (plot) and a text view. If you change the data, two views must know to update themselves, and that's what the viewer is responsible for. This is a very common problem, and its solution is included in the standard Java.util library.
In Java, there are two types of objects used to implement the observer paradigm. Among them, the Observable class is used to track all individuals who want to be notified when a change occurs-regardless of whether the "state" has changed. If someone says, "Well, everyone has to check themselves and maybe update", then the observable class performs this task--calling the Notifyobservers () method for each "person" in the list. The Notifyobservers () method is part of the underlying class observable.
In the observer paradigm, there are actually two aspects that can change: the number of objects observed and how they are updated. In other words, the observer paradigm allows us to modify both aspects without interfering with the other code around it.
Here's an example: Chests (Boxes) are placed in a screen grid, each initializing a random color. In addition, each box is "implemented" (implement) an "observer" (Observer) interface, and is registered with a observable object. If you click on a box, all other boxes will receive a notification stating that a change has occurred.
This is because the observable object automatically calls the update () method of each observer object. In this method, the box checks whether the box in the point is adjacent to itself. If the answer is yes, then change your color and keep it in harmony with the box in the point.
1 Code
import java.awt.*;
import java.awt.event.*;
import java.util.*;
You must inherit a new type of Observable:
class Boxobservableextends Observable {
Public voidnotifyobservers (Object b) {
//Otherwise it won ' t propagate changes:
Setchanged ();
Super. Notifyobservers (b);
}
}
Public class Boxobserver extends Frame {
Observable notifier =new boxobservable ();
Public Boxobserver (intgrid) {
Settitle ("demonstrates Observer pattern");
SetLayout (new GridLayout (grid,grid));
for (intx = 0; x < grid; x+ +)
for (inty = 0; y < grid; y+ +)
Add (new Ocbox (x,y, notifier));
}
Public staticvoidmain (string[]args) {
int grid = 8;
if (args. length> 0)
grid = Integer. parseint (args[0]);
Frame F =new boxobserver (grid);
F.setSize (500, 400);
f. setvisible (true);
F.Addwindowlistener (new windowadapter () {
Public void windowclosing (windowevent e) {
System. Exit (0);
}
});
}
}
class Ocbox extends Canvas implements Observer {
Observable notifier;
int x, y; //Locations in grid
Color Ccolor =newcolor();
static final color[] colors = {Color. black , color. blue , color. cyan , color. darkgray , color. gray , color. green ,
Color. lightgray, Color. Magenta, Color. Orange, Color. Pink, Color. Red, Color. White, Color. Yellow };
staticfinal Color Newcolor () {
returncolors [(int) (Math. Random() *colors. length)];
}
Ocbox (intx, inty, Observablenotifier) {
this. x =x;
this. y =y;
notifier. Addobserver (this);
this. notifier =notifier;
Addmouselistener (new ML ());
}
Public voidpaint (Graphics g) {
G.setcolor (ccolor);
Dimension S = GetSize ();
G.fillRect (0, 0,s. Width, s. height);
}
class MLextendsmouseadapter {
Public void mousepressed (MouseEvent e) {
notifier. Notifyobservers (Ocbox. this);
}
}
Public voidupdate (Observable o, Object arg) {
Ocbox Clicked = (ocbox)arg;
if (NextTo (clicked)) {
ccolor =clicked. Ccolor;
Repaint ();
}
}
PrivatefinalbooleannextTo (ocboxb) {
return Math. ABS (x -b. x) <= 1 &&math. ABS (y-b. y) <= 1;
}
} /// :~
If you're looking at observable's online help documentation for the first time, you might feel a little confused because it seems to indicate that you can manage updates with an original observable object. But this argument is not tenable; You can try it yourself-in boxobserver, create a observable object, replace the Boxobservable object, and see what happens. As a matter of fact, nothing is going to happen. To really produce an effect, you must inherit from observable and call setchanged () somewhere in the derived class code. This method needs to set the "changed" (changed) flag, which means that when we call Notifyobservers (), all observers will in fact receive a notification. In the example above, setchanged () is simply called in Notifyobservers (), and you can decide when to call Setchanged () based on any criteria that match the actual situation.
The boxobserver contains a single observable object, named Notifier. Each time a Ocbox object is created, it is associated with the notifier. In Ocbox, a call to the Notifyobservers () method is made as soon as the mouse is clicked, and the object in the point is passed in as a parameter, so that all chests that receive the message (with their update () method) can know who is being ordered. and determine whether or not you want to change. With the combination of the Code in Notifyobservers () and update (), we can cope with some very complex situations.
In the Notifyobservers () method, it appears that the way the observer receives notifications must be fixed during compilation. However, if you look at the above code a little bit, you will find that the only place in Boxobserver or ocbox to be aware of the use of boxobservable is when the observable object is created-from that point on, Everything will use the basic observable interface. This means that in the future, if you want to change the notification mode, you can inherit other observable classes and exchange them during run time.
76.JAVA Programming Idea-observer paradigm