epubjs
Version:
Render ePub documents in the browser, across many devices
68 lines (67 loc) • 9.13 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Observers and Observables</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Observers and Observables"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-11-SECT-8"/>Observers and Observables</h1></div></div></div><p><a id="idx10632" class="indexterm"/> <a id="idx10663" class="indexterm"/>The <a id="I_indexterm11_id750326" class="indexterm"/><code class="literal">java.util.Observer</code>
interface and <a id="I_indexterm11_id750337" class="indexterm"/><code class="literal">java.util.Observable</code>
class are relatively small utilities, but they provide a glimpse of a
fundamental design pattern in Java. Observers and observables are part of
the MVC (Model-View-Controller) framework. It is an abstraction that lets
a number of client objects (the <span class="emphasis"><em>observers</em></span>) be
notified whenever a certain object or resource (the
<span class="emphasis"><em>observable</em></span>) changes in some way. We will see this
pattern used extensively in Java’s event mechanism, which is covered in
Chapters <a class="xref" href="ch16.html" title="Chapter 16. Swing">16</a> through <a class="xref" href="ch19.html" title="Chapter 19. Layout Managers">19</a>. Although
these classes are not often used directly, it’s worth looking at them in
order to understand the pattern.</p><p>The <code class="literal">Observable</code> object has a
method that an <code class="literal">Observer</code> calls to
register its interest. When a change happens, the <code class="literal">Observable</code> sends a notification by calling a
method in each of the <code class="literal">Observer</code>s. The
observers implement the <code class="literal">Observer</code>
interface, which specifies that notification causes an <code class="literal">Observer</code> object’s <code class="literal">update()</code> method to be called.</p><p>In the following example, we create a <code class="literal">MessageBoard</code> object that holds a <code class="literal">String</code> message. <code class="literal">MessageBoard</code> extends <code class="literal">Observable</code>, from which it inherits the mechanism
for registering observers (<code class="literal">addObserver()</code>) and notifying observers (<code class="literal">notifyObservers()</code>). To observe the <code class="literal">MessageBoard</code>, we have <code class="literal">Student</code> objects that implement the <code class="literal">Observer</code> interface so that they can be notified
when the message changes:</p><a id="I_11_tt758"/><pre class="programlisting"> <code class="c1">//file: MessageBoard.java</code>
<code class="kn">import</code> <code class="nn">java.util.*</code><code class="o">;</code>
<code class="err"> </code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">MessageBoard</code> <code class="kd">extends</code> <code class="n">Observable</code> <code class="o">{</code>
<code class="kd">private</code> <code class="n">String</code> <code class="n">message</code><code class="o">;</code>
<code class="err"> </code>
<code class="kd">public</code> <code class="n">String</code> <code class="nf">getMessage</code><code class="o">()</code> <code class="o">{</code>
<code class="k">return</code> <code class="n">message</code><code class="o">;</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">changeMessage</code><code class="o">(</code> <code class="n">String</code> <code class="n">message</code> <code class="o">)</code> <code class="o">{</code>
<code class="k">this</code><code class="o">.</code><code class="na">message</code> <code class="o">=</code> <code class="n">message</code><code class="o">;</code>
<code class="n">setChanged</code><code class="o">();</code>
<code class="n">notifyObservers</code><code class="o">(</code> <code class="n">message</code> <code class="o">);</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code> <code class="n">String</code> <code class="o">[]</code> <code class="n">args</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">MessageBoard</code> <code class="n">board</code> <code class="o">=</code> <code class="k">new</code> <code class="n">MessageBoard</code><code class="o">();</code>
<code class="n">Student</code> <code class="n">bob</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Student</code><code class="o">();</code>
<code class="n">Student</code> <code class="n">joe</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Student</code><code class="o">();</code>
<code class="n">board</code><code class="o">.</code><code class="na">addObserver</code><code class="o">(</code> <code class="n">bob</code> <code class="o">);</code>
<code class="n">board</code><code class="o">.</code><code class="na">addObserver</code><code class="o">(</code> <code class="n">joe</code> <code class="o">);</code>
<code class="n">board</code><code class="o">.</code><code class="na">changeMessage</code><code class="o">(</code><code class="s">"More Homework!"</code><code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code> <code class="c1">// end of class MessageBoard</code>
<code class="err"> </code>
<code class="kd">class</code> <code class="nc">Student</code> <code class="kd">implements</code> <code class="n">Observer</code> <code class="o">{</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">update</code><code class="o">(</code><code class="n">Observable</code> <code class="n">o</code><code class="o">,</code> <code class="n">Object</code> <code class="n">arg</code><code class="o">)</code> <code class="o">{</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="s">"Message board changed: "</code> <code class="o">+</code> <code class="n">arg</code> <code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>Our <code class="literal">MessageBoard</code> object extends
<code class="literal">Observable</code>, which provides a method
called <a id="I_indexterm11_id750509" class="indexterm"/><code class="literal">addObserver()</code>. Each
<code class="literal">Student</code> object registers itself using
this method and receives updates via its <code class="literal">update()</code> method. When a new message string is
set using the <code class="literal">MessageBoard</code>’s <code class="literal">changeMessage()</code> method, the <code class="literal">Observable</code> calls the <a id="I_indexterm11_id750547" class="indexterm"/><code class="literal">setChanged()</code> and <code class="literal">notifyObservers()</code> methods to notify the
observers. <code class="literal">notifyObservers()</code> can take
as an argument an <code class="literal">Object</code> to pass along
as an indication of the change. This object—in this case, the <code class="literal">String</code> containing the new message—is passed to
the observer’s <code class="literal">update()</code> method as its
second argument. The first argument to <code class="literal">update()</code> is the <code class="literal">Observable</code> object itself.</p><p>The <code class="literal">main()</code> method of <code class="literal">MessageBoard</code> creates a <code class="literal">MessageBoard</code> and registers two <code class="literal">Student</code> objects with it. Then it changes the
message. When you run the code, you should see each <code class="literal">Student</code> object print the message as it is
notified.</p><p>You can imagine how you could implement the observer/observable
relationship yourself using a <code class="literal">List</code> to
hold the list of observers. In <a class="xref" href="ch16.html" title="Chapter 16. Swing">Chapter 16</a> and
beyond, we’ll see that the Java AWT and Swing event model extends this
design pattern to use strongly typed observables and observers, which are
called events and event listeners. But for now, we turn our discussion of
core utilities to another fundamental topic: I/O.<a id="I_indexterm11_id750647" class="indexterm"/><a id="I_indexterm11_id750654" class="indexterm"/></p></div></body></html>