Translation tipatterns - System decoupling

xiaoxiao2021-03-06  112

System decoupling

Observer mode (OBServer)

Similar to other forms of callback functions, the OBServer mode also allows you to change the code by hook Point. The difference is that from essentially, the OBServer mode is completely dynamic. It is often used to change its own (status), and it is often the basic component of the event management system according to the status change of other objects, and it is often the basic component of the event management system. Whenever, when you need to separate the call source with a fully dynamic manner, when you call the code, (Observer mode is your first choice). (The last sentence seems to have not been written)

Observer mode is a fairly common question: When an object changes state, another group (related to it) is how to update them. For example, the "model-view" structure in SmallTalk, (it is part of the MVC-View-Controller structure), such as the basic and comparable "document-view" structure. Suppose you have some data (that is, "document") and more than one view, such as a chart (plot) and a text view. When you change the data, these two views must be known (as needed) to update themselves, which is the problem that the OBServer mode has to help you solve. This problem is so common, so that its solution has become part of a standard Java.util library.

Implementing OBServer mode with Java requires two types of objects, the OBSERVABLE class is responsible for notify which classes need to be notified when changing, regardless of "status" changes or not. When observed, "OK, you (refer to the observer) can update your own as needed," OBSERVABLE class, by calling the NotifyObservers () method to notify each observer on the list, and complete this task. NotifyobServers () is a method of base class OBSERVABLE.

In fact, the OBServer mode is really changing with two things: the number of ObserVing Objects and how they update themselves. That is, the OBServer mode makes you only change the code for both changes without having to change other code.

. . . . . . (The author has not been written)

Observer is actually an interface class with only one member function. This member function is UPDATE (). When the observer decides to update all the observer, it calls the Update () function. Whether it is necessary to pass the parameters is optional; even if there is no parameter () function, it is also in line OBServer mode; however, more common practice is to let the observer (via the Update () function) caused an updated object (that is Itself passing by itself to the observer because an observer may register more than one observer. In this way, the observer object does not have to find the update caused by the observer, and the information it needs has also been passed.

Decide when and how to initiate updates (Updating) is named OBSERVABLE. The Observable class uses a flag (FLAG) to indicate whether it is changed. For relatively simple designs, no flash is also possible; if there is change, all observes are notified. If you use Flag, you can delay the time of the notification, and you will decide to notify the observer when you are right. However, please note that the method of controlling the FLAG status is protected, that is, only (OBSERVABLE class) derived class can determine which things can constitute a change (Constitues a change) instead of derived class by Observer The end user is determined.

Most of the work is done in NotifyObservers (). If FLAG is set to "changed", NOTIFYOBSERVERS () does not do anything; otherwise, it first clears the "changed" state of the FLAG, so that it is wasted when you repeat the NotifyObservers (). This is observable object.

Then the NotifyObservers () method traverses the observer sequence it saved and calls each observer's Update () member function.

It seems that you can manage updates with a normal OBSERVABLE object. But actually don't do; in order to achieve this effect, you must inherit the OBSERVABLE class and call the setChanged () method in the code of the derived class. It is used to set FLAG to "changed" member functions, which, when you call notifyObservers (), all observes will be accurately notified. Whereverby call setChanged (), depending on your program's logical structure.

Observing the flowers is an example of the OBServer mode.

//: observer: ObservedFlower.java// Demonstration of "observer" pattern.package observer; import java.util *; import junit.framework *; class Flower {private boolean isOpen; private OpenNotifier oNotify = new OpenNotifier ();.. private CloseNotifier cNotify = new CloseNotifier (); public Flower () {isOpen = false;} public void open () {// Opens its petals isOpen = true; oNotify.notifyObservers (); cNotify.open ();} public void close () {// Closes its petals isOpen = false; cNotify.notifyObservers (); oNotify.close ();} public Observable opening () {return oNotify;} public Observable closing () {return cNotify;} private class OpenNotifier extends Observable {private boolean alreadyOpen = false; public void notifyObservers () {if (isOpen && alreadyOpen!) {setChanged (); super.notifyObservers (); alreadyOpen = true;}} public void close () {alreadyOpen = false;}} private Class Closenotifier Extends Observable { private boolean alreadyClosed = false; public void notifyObservers () {if (!! isOpen && alreadyClosed) {setChanged (); super.notifyObservers (); alreadyClosed = true;}} public void open () {alreadyClosed = false;}}} class Bee {private String name; private OpenObserver openObsrv = new OpenObserver (); private CloseObserver closeObsrv = new CloseObserver (); public Bee (String nm) {name = nm;} // An inner class for observing openings: private class OpenObserver implements Observer {public void update (Observable ob, object a) {system.out.println ("Bee" Name "'

s breakfast time ");}} // Another inner class for closings: private class CloseObserver implements Observer {public void update (Observable ob, Object a) {System.out.println ("! Bee " name " 's bed time ");!}} public Observer openObserver () {return openObsrv;} public Observer closeObserver () {return closeObsrv;}} class Hummingbird {private String name; private OpenObserver openObsrv = new OpenObserver (); private CloseObserver closeObsrv = new CloseObserver (); public Hummingbird (String nm) {name = nm;} private class OpenObserver implements Observer {public void update (Observable ob, Object a) {System.out.println ( "Hummingbird" name " 's breakfast time! ");}} private class CloseObserver implements Observer {public void update (Observable ob, Object a) {System.out.println (" Hummingbird " name " 's bed time ");!}} public Observer openObserver () {Return OpenObsrv;} PUBLIC Observer closeObserver () {return closeObsrv;}} public class ObservedFlower extends TestCase {Flower f = new Flower (); Bee ba = new Bee ( "A"), bb = new Bee ( "B"); Hummingbird ha = new Hummingbird ("A"), hb = new hummingbird ("b"); public void test () {f .opening (); addobserver (ha.openobserver ()); f.Opening (). Addobserver (hb.openobserver () F.Opensening (). Addobserver (); f.Opening (). Addobserver (bb.openobserver ()); f.closing (). Addobserver (ha.closeobserver ()); f.closing () .addobserver (HB.Closeobserver ());

f.closing (). addobserver ()); f.closing (). addobserver (bb.closeobserver ()); // hummingbird b decides to sleep in: f.Opening (). deleteobserver (Hb.OpenobServer ()); // a change That INTERESTS OBSERVERS: F.Open (); f.Open (); // it's already open, no change. // bee a doesn't want to go to bed: f.closing ). deleteObserver (ba.closeobserver ()); f.close (); f.close (); // it's already closed; no change; f.Opens (); f.open (); f.close (); Public static void main (string args []) {junit.textui.teStrunner.Run (ObservedFlower.class);}} ///: ~ (observer) Interested event is the opening and closing of flowers Open or close. Because there is an internal class (INNER CLASS), these two events can be viewed separately. Both OpenNotifier and Closenotifier are inherited from Observable, they can use the setchanged () method, which can be passed to where the OBServable object is passed to a place where an OBSERVABLE object is passed. It is also very convenient to use Inner Class to define multiple Observer, for BEE and Hummingbird (Hummingbird), which may need to open and close each other. Please note that by using Inner Class, we have achieved some benefits that can be obtained by inheritance, and further, through Inner Class, you can also access private data members of the external class, which is the inheritance. In the main () function, you can see the biggest benefits brought by the OBServer mode: Change the behavior of the observer at runtime by registering and unloading the observer object (OBSERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVERVA) . Studying the above code You will find that OpenNotifier and ClosNotifier use only the basic interface of the OBServable class. (This seems that the author is not finished, it feels unconstrained) This means you can also inherit other completely different Observer classes; the only link between the observer and the flowers is the OBServer interface.

About an visual example of OBSERVERS The following example is like Thinking In Java Second Edition Chapter 14 ColorBoxes that example. On the screen grid (Boxes), color these blocks with randomly selected colors. In addition to these, each block implements the OBSERVER interface and registers an OBSERVABLE object. When you click on a block, all other squares will be notified because the OBSERVABLE object automatically calls the Update () function of each OBServer object. In the Update () function, the block object will check (location information) to see if you are with the clicked block, if it is adjacent to it, the same is true.

//: observer: BoxObserver.java// Demonstration of Observer pattern using // Java's built-in observer classes.package observer; import javax.swing *; import java.awt *; import java.awt.event *;... import java.util *; // You must inherit a new type of Observable:. class BoxObservable extends Observable {public void notifyObservers (Object b) {// Otherwise it will not propagate changes: setChanged (); super.notifyObservers (b );}} public class BoxObserver extends JFrame {Observable notifier = new BoxObservable (); public BoxObserver (int grid) {setTitle ( "Demonstrates Observer pattern"); Container cp = getContentPane (); cp.setLayout (new GridLayout (grid, Grid)); for (int x = 0; x 0) Grid = INTEGER.PARSEINT (Args [0]); JFrame F = New BoxobServer (Grid); F.setsize (500, 400); F.setVisible (TRUE); FS etDefaultCloseOperation (EXIT_ON_CLOSE);}} class OCBox extends JPanel implements Observer {Observable notifier; int x, y; // Locations in grid Color cColor = newColor (); static final Color [] colors = {Color.BLACK, Color.BLUE, Color.cyan, color.dark_gray, color.gray, color.green, color.light_gray, color.magenta, color.range, color.pink, color.red, color.white, color.yellow}; static random rand = new Random (); Static Final Color NewColor () {Return Colors [Rand.Nextint (Colors.Length)];} OcBox (int X, int y, observable notifier) ​​{this.x = x; this.y = y; Notifier .addobserver (this); this.notifier =

Notifier; AddMouseListener (new ml ());} public void PaintComponent (GRAPHICS G) {Super.PaintComponent (g); g.setColor (ccolor); Dimension S = getSize (); g.FillRect (0, 0, s. width, s.height);} class ML extends MouseAdapter {public void mousePressed (MouseEvent e) {notifier.notifyObservers (OCBox.this);}} public void update (Observable o, Object arg) {OCBox clicked = (OCBox) arg {Ccolor = clicked.ccolor; repaint ();}} private final boolean nextto (o = 1 && math.abs (x - BX) <= 1 && math.abs (y - by <= 1;}} ////: ~ When you start watching Observable online help, there is a little more confused. From the document, you can use a normal OBSERVABLE object to manage updates (Updates) . But actually don't do it; you can try - Change the BoxobServer class, (directly) Create an OBSERVABLE class instead of the BoxobServable class, then look at what will happen: actually, nothing will happen. To make Update take effect, you must first inherit the OBSERVABLE class, then call the setChanged () method in the derived class code. This method sets the "ChangeD" flag (Flag), which means that all observers (OBSERVERS) will not know when you call NOTIFYOBSERVERS (). In the above example, the setChanged () method is just a simple in notifyobservers (), but you can use any (other) guidelines to determine when calling the setChanged () method.

The BoxobServer class only includes an OBSERVABLE object, which is Notifier, when you create a new Ocbox object, it will be binded to Notifier (TIED). In Ocbox, whenever you click the mouse, you will trigger the notifyobservers () method, and then click the click object as a parameter to other square objects, so receive this message (by their own Update () method) The square object knows which block being clicked, and then decide whether you need to change yourself. You can implement some fairly complicated things by combining the code provided by the NotifyObservers () and Update () methods.

It seems that it seems to be able to deliver how to notify the observer object through the NotifyObservers () method. However, if you carefully see the above code, you will find that whether it is for BoxobServable or Ocbox, only where you create an OBSERVABLE object, you will realize that you have cleared the boxobservable, after the creation is complete, all work It is done through the basic interface provided by Observable. This means that if you want to change the NOTIFICATION BEHAVIOR, you can implement them by inheriting other Observable classes and exchange them in runtime. Mediator Sweep Coupling Under The Rug, HOW IS THIS DIFFERENT FROM MVC MVC HAS DISTINCT Model And View; Mediator Could Be Anything. MVC A Flavor of Mediator Exercise 1. Give a simplest Observer-ObserVable design. Just need to write the methods necessary for two classes (minimum). Then create an OBSERVABLE object and multiple OBSERVERS objects and update (Update) Observers objects with Observable objects. 2. Write a very simplified Observer system, using java.util.timer inside your OBSERVABLE class to generate events that need to be reported to OBSERVERS. Create a few different Observer objects with internal classes and register them to the OBSERVABLE object. When the Timer event triggered, Observers must be notified. 3. Change BoxobServer.java and turn it into a simple game. For any other block around the one of the clicked, if it belongs to an interconnected collision zone, all the squares belonging to this color area is changed to the same color as the clicked square (this sentence is exhausted . You can change it into a multi-player competition by changing the game's configuration, or you can record a single player to complete the number of steps used in the game (refer to all squares into the same color). You can also limit the player only as the color selected by its first step as the final colors.

table of Contents

转载请注明原文地址:https://www.9cbs.com/read-124407.html

New Post(0)