⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter16.html

📁 java 是一个很好的网络开发环境。由于它是通过解释的方法
💻 HTML
📖 第 1 页 / 共 5 页
字号:
Classifying patterns</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <I>Design Patterns</I> book
discusses 23 different patterns, classified under three purposes (all of which
revolve around the particular aspect that can vary). The three purposes are:
<A NAME="Index2917"></A><A NAME="Index2918"></A><A NAME="Index2919"></A><A NAME="Index2920"></A><A NAME="Index2921"></A><A NAME="Index2922"></A></FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Georgia"><B>	Creational</B>: how an object can be created.
This often involves isolating the details of object creation so your code
isn&#8217;t dependent on what types of objects there are and thus doesn&#8217;t
have to be changed when you add a new type of object. The aforementioned
<I>Singleton</I> is classified as a creational pattern, and later in this
chapter you&#8217;ll see examples of <I>Factory Method</I> and
<I>Prototype</I>.</FONT><LI><FONT FACE="Georgia"><B>	Structural</B>:
designing objects to satisfy particular project constraints. These work with the
way objects are connected with other objects to ensure that changes in the
system don&#8217;t require changes to those
connections.</FONT><LI><FONT FACE="Georgia"><B>	Behavioral</B>: objects
that handle particular types of actions within a program. These encapsulate
processes that you want to perform, such as interpreting a language, fulfilling
a request, moving through a sequence (as in an iterator), or implementing an
algorithm. This chapter contains examples of the <I>Observer</I> and the
<I>Visitor</I>
patterns.</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <I>Design
Patterns</I> book has a section on each of its 23 patterns along with one or
more examples for each, typically in C++ but sometimes in Smalltalk.
(You&#8217;ll find that this doesn&#8217;t matter too much since you can easily
translate the concepts from either language into Java.) This book will not
repeat all the patterns shown in <I>Design Patterns</I> since that book stands
on its own and should be studied separately. Instead, this chapter will give
some examples that should provide you with a decent feel for what patterns are
about and why they are so
important.</FONT><A NAME="_Toc375545413"></A><A NAME="_Toc408018797"></A><BR></P></DIV>
<A NAME="Heading554"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
The observer pattern</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The
<A NAME="Index2923"></A><A NAME="Index2924"></A>observer pattern solves a fairly
common problem: What if a group of objects needs to update themselves when some
object changes state? This can be seen in the &#8220;model-view&#8221; aspect of
Smalltalk&#8217;s MVC (model-view-controller), or the almost-equivalent
&#8220;Document-View Architecture.&#8221; Suppose that you have some data (the
&#8220;document&#8221;) and more than one view, say a plot and a textual view.
When you change the data, the two views must know to update themselves, and
that&#8217;s what the observer facilitates. It&#8217;s a common enough problem
that its solution has been made a part of the standard <B>java.util</B>
library.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are two types of objects used
to implement the observer pattern in Java. The
<A NAME="Index2925"></A><B>Observable</B> class keeps track of everybody who
wants to be informed when a change happens, whether the &#8220;state&#8221; has
changed or not. When someone says &#8220;OK, everybody should check and
potentially update themselves,&#8221; the <B>Observable</B> class performs this
task by calling the <A NAME="Index2926"></A><B>notifyObservers(&#160;)</B>
method for each one on the list. The <B>notifyObservers(&#160;)</B> method is
part of the base class <B>Observable</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are actually two
&#8220;things that change&#8221; in the observer pattern: the quantity of
observing objects and the way an update occurs. That is, the observer pattern
allows you to modify both of these without affecting the surrounding
code.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The following example is similar to
the <B>ColorBoxes</B> example from Chapter 14. Boxes are placed in a grid on the
screen and each one is initialized to a random color. In addition, each box
<B>implements</B> the <A NAME="Index2927"></A><B>Observer</B> interface and is
registered with an <B>Observable</B> object. When you click on a box, all of the
other boxes are notified that a change has been made because the
<B>Observable</B> object automatically calls each <B>Observer </B>object&#8217;s
<B>update(&#160;)</B> method. Inside this method, the box checks to see if
it&#8217;s adjacent to the one that was clicked, and if so it changes its color
to match the clicked box.</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: BoxObserver.java</font>
<font color=#009900>// Demonstration of Observer pattern using</font>
<font color=#009900>// Java's built-in observer classes.</font>
<font color=#0000ff>import</font> java.awt.*;
<font color=#0000ff>import</font> java.awt.event.*;
<font color=#0000ff>import</font> java.util.*;

<font color=#009900>// You must inherit a new type of Observable:</font>
<font color=#0000ff>class</font> BoxObservable <font color=#0000ff>extends</font> Observable {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> notifyObservers(Object b) {
    <font color=#009900>// Otherwise it won't propagate changes:</font>
    setChanged();
    <font color=#0000ff>super</font>.notifyObservers(b);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> BoxObserver <font color=#0000ff>extends</font> Frame {
  Observable notifier = <font color=#0000ff>new</font> BoxObservable();
  <font color=#0000ff>public</font> BoxObserver(<font color=#0000ff>int</font> grid) {
    setTitle(<font color=#004488>"Demonstrates Observer pattern"</font>);
    setLayout(<font color=#0000ff>new</font> GridLayout(grid, grid));
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> x = 0; x &lt; grid; x++)
      <font color=#0000ff>for</font>(<font color=#0000ff>int</font> y = 0; y &lt; grid; y++)
        add(<font color=#0000ff>new</font> OCBox(x, y, notifier));
  }   
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    <font color=#0000ff>int</font> grid = 8;
    <font color=#0000ff>if</font>(args.length &gt; 0)
      grid = Integer.parseInt(args[0]);
    Frame f = <font color=#0000ff>new</font> BoxObserver(grid);
    f.setSize(500, 400);
    f.setVisible(<font color=#0000ff>true</font>);
    f.addWindowListener(
      <font color=#0000ff>new</font> WindowAdapter() {
        <font color=#0000ff>public</font> <font color=#0000ff>void</font> windowClosing(WindowEvent e) {
          System.exit(0);
        }
      });
  }
}

<font color=#0000ff>class</font> OCBox <font color=#0000ff>extends</font> Canvas <font color=#0000ff>implements</font> Observer {
  Observable notifier;
  <font color=#0000ff>int</font> x, y; <font color=#009900>// Locations in grid</font>
  Color cColor = newColor();
  <font color=#0000ff>static</font> <font color=#0000ff>final</font> 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 
  };
  <font color=#0000ff>static</font> <font color=#0000ff>final</font> Color newColor() {
    <font color=#0000ff>return</font> colors[
      (<font color=#0000ff>int</font>)(Math.random() * colors.length)
    ];
  }
  OCBox(<font color=#0000ff>int</font> x, <font color=#0000ff>int</font> y, Observable notifier) {
    <font color=#0000ff>this</font>.x = x;
    <font color=#0000ff>this</font>.y = y;
    notifier.addObserver(<font color=#0000ff>this</font>);
    <font color=#0000ff>this</font>.notifier = notifier;
    addMouseListener(<font color=#0000ff>new</font> ML());
  }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> paint(Graphics  g) {
    g.setColor(cColor);
    Dimension s = getSize();
    g.fillRect(0, 0, s.width, s.height);
  }
  <font color=#0000ff>class</font> ML <font color=#0000ff>extends</font> MouseAdapter {
    <font color=#0000ff>public</font> <font color=#0000ff>void</font> mousePressed(MouseEvent e) {
      notifier.notifyObservers(OCBox.<font color=#0000ff>this</font>);
    }
  }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> update(Observable o, Object arg) {
    OCBox clicked = (OCBox)arg;
    <font color=#0000ff>if</font>(nextTo(clicked)) {
      cColor = clicked.cColor;
      repaint();
    }
  }
  <font color=#0000ff>private</font> <font color=#0000ff>final</font> <font color=#0000ff>boolean</font> nextTo(OCBox b) {
    <font color=#0000ff>return</font> Math.abs(x - b.x) &lt;= 1 &amp;&amp; 
           Math.abs(y - b.y) &lt;= 1;
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When you first look at the online
documentation for <B>Observable</B>, it&#8217;s a bit confusing because it
appears that you can use an ordinary <B>Observable</B> object to manage the
updates. But this doesn&#8217;t work; try it &#8211; inside <B>BoxObserver</B>,
create an <B>Observable</B> object instead of a <B>BoxObservable</B> object and
see what happens: nothing. To get an effect, you <I>must</I> inherit from
<B>Observable</B> and somewhere in your derived-class code call
<A NAME="Index2928"></A><B>setChanged(&#160;)</B>. This is the method that sets
the &#8220;changed&#8221; flag, which means that when you call
<A NAME="Index2929"></A><B>notifyObservers(&#160;)</B> all of the observers
will, in fact, get notified. In the example above <B>setChanged(&#160;)</B> is
simply called within <B>notifyObservers(&#160;)</B>, but you could use any
criterion you want to decide when to call <B>setChanged(&#160;)</B>.
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>BoxObserver</B> contains a
single <B>Observable </B>object called <B>notifier</B>, and every time an
<B>OCBox</B> object is created, it is tied to <B>notifier</B>. In <B>OCBox</B>,
whenever you click the mouse the <B>notifyObservers(&#160;)</B> method is
called, passing the clicked object in as an argument so that all the boxes
receiving the message (in their <B>update(&#160;) </B>method) know who was
clicked and can decide whether to change themselves or not. Using a combination
of code in <B>notifyObservers(&#160;)</B> and <B>update(&#160;)</B> you can work
out some fairly complex schemes.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It might appear that the way the
observers are notified must be frozen at compile time in the
<B>notifyObservers(&#160;)</B> method. However, if you look more closely at the
code above you&#8217;ll see that the only place in <B>BoxObserver</B> or
<B>OCBox</B> where you're aware that you&#8217;re working with a
<B>BoxObservable</B> is at the point of creation of the <B>Observable </B>object
&#8211; from then on everything uses the basic <B>Observable</B> interface. This
means that you could inherit other <B>Observable</B> classes and swap them at
run-time if you want to change notification behavior
then.</FONT><A NAME="_Toc408018798"></A><BR></P></DIV>
<A NAME="Heading555"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Simulating the trash recycler</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The nature of this problem is that
the trash is thrown unclassified into a single bin, so the specific type
information is lost. But later, the specific type information must be recovered
to properly sort the trash. In the initial solution, RTTI (described in Chapter
11) is used.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is not a trivial design
because it has an added constraint. That&#8217;s what makes it interesting
&#8211; it&#8217;s more like the messy problems you&#8217;re likely to encounter
in your work. The extra constraint is that the trash arrives at the trash
recycling plant all mixed together. The program must model the sorting of that
trash. This is where RTTI comes in: you have a bunch of anonymous pieces of
trash, and the program figures out exactly what type they are.</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: RecycleA.java </font>
<font color=#009900>// Recycling with RTTI</font>
<font color=#0000ff>package</font> c16.recyclea;
<font color=#0000ff>import</font> java.util.*;
<font color=#0000ff>import</font> java.io.*;

<font color=#0000ff>abstract</font> <font color=#0000ff>class</font> Trash {
  <font color=#0000ff>private</font> <font color=#0000ff>double</font> weight;
  Trash(<font color=#0000ff>double</font> wt) { weight = wt; }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -