Tải bản đầy đủ (.pdf) (11 trang)

Java design patterns 101 phần 2 pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (132.04 KB, 11 trang )

Section 5. Structural patterns
Overview
Structural patterns prescribe the organization of classes and objects. These patterns are
concerned with how classes inherit from each other or how they are composed from other
classes.
Common structural patterns include Adapter, Proxy, and Decorator patterns. These patterns
are similar in that they introduce a level of indirection between a client class and a class it
wants to use. Their intents are different, however. Adapter uses indirection to modify the
interface of a class to make it easier for a client class to use it. Decorator uses indirection to
add behavior to a class, without unduly affecting the client class. Proxy uses indirection to
transparently provide a stand-in for another class.
The Adapter pattern
The Adapter pattern is typically used to allow the reuse of a class that is similar, but not the
same, as the class the client class would like to see. Typically the original class is capable of
supporting the behavior the client class needs, but does not have the interface the client
class expects, and it is not possible or practical to alter the original class. Perhaps the source
code is not available, or it is used elsewhere and changing the interface is inappropriate.
Here is an example that wraps OldClass so a client class can call it using a method,
NewMethod() defined in NewInterface:
public class OldClassAdapter implements NewInterface {
private OldClass ref;
public OldClassAdapter(OldClass oc)
{
ref = oc;
}
public void NewMethod()
{
ref.OldMethod();
}
}
Presented by developerWorks, your source for great tutorials


ibm.com/developerWorks
Java design patterns 101 Page 12 of 22
The Proxy and Decorator patterns
A Proxy is a direct stand-in for another class, and it typically has the same interface as that
class because it implements a common interface or an abstract class. The client object is not
aware that it is using a proxy. A Proxy is used when access to the class the client would like
to use must be mediated in a way that is apparent to the client because it requires
restricted access or is a remote process, for example.
Decorator, like Proxy, is also a stand-in for another class, and it also has the same interface
as that class, usually because it is a subclass. The intent is different, however. The purpose
of the Decorator pattern is to extend the functionality of the original class in a way that is
transparent to the client class.
Examples of the Decorator pattern in the Java API are found in the classes for processing
input and output streams. BufferedReader(), for example, makes reading text from a file
convenient and efficient:
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
The Composite pattern
The Composite pattern prescribes recursive composition for complex objects. The intent is to
allow all component objects to be treated in a consistent manner. All objects, simple and
complex, that participate in this pattern derive from a common abstract component class that
defines common behavior.
Forcing relationships into a part-whole hierarchy in this way minimizes the types of objects
that our system (or client subsystem) needs to manage. A client of a paint program, for
example, could ask a line to draw itself in the same way it would ask any other object,
including a composite object.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 13 of 22
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks

Java design patterns 101 Page 14 of 22
Section 6. Behavioral patterns
Overview
Behavioral patterns prescribe the way objects interact with each other. They help make
complex behavior manageable by specifying the responsibilities of objects and the ways they
communicate with each other.
The Observer pattern
Observer is a very common pattern. You typically use this pattern when you're implementing
an application with a Model/View/Controller architecture. The Model/View part of this design
is intended to decouple the presentation of data from the data itself.
Consider, for example, a case where data is kept in a database and can be displayed in
multiple formats, as a table or a graph. The Observer pattern suggests that the display
classes register themselves with the class responsible for maintaining the data, so they can
be notified when the data changes, and so they can update their displays.
The Java API uses this pattern in the event model of its AWT/Swing classes. It also provides
direct support so this pattern can be implemented for other purposes.
The Java API provides an Observable class that can be subclassed by objects that want to
be observed. Among the methods Observable provides are:
* addObserver(Observer o) is called by Observable objects to register
themselves.
* setChanged() marks the Observable object as having changed.
* hasChanged() tests if the Observable object has changed.
* notifyObservers() notifies all observers if the Observable object has changed,
according to hasChanged().
To go along with this, an Observer interface is provided, containing a single method that is
called by an Observable object when it changes (providing the Observer has registered
itself with the Observable class, of course):
public void update(Observable o, Object arg)
The following example demonstrates how an Observer pattern can be used to notify a
display class for a sensor such as temperature has detected a change:

import java.util.*;
class Sensor extends Observable {
private int temp = 68;
void takeReading()
{
double d;
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 15 of 22
d =Math.random();
if(d>0.75)
{
temp++;
setChanged();
}
else if (d<0.25)
{
temp ;
setChanged();
}
System.out.print("[Temp: " + temp + "]");
}
public int getReading()
{
return temp;
}
}
public class Display implements Observer {
public void update(Observable o, Object arg)
{

System.out.print("New Temp: " + ((Sensor) o).getReading());
}
public static void main(String []ac)
{
Sensor sensor = new Sensor();
Display display = new Display();
// register observer with observable class
sensor.addObserver(display);
// Simulate measuring temp over time
for(int i=0; i < 20; i++)
{
sensor.takeReading();
sensor.notifyObservers();
System.out.println();
}
}
}
The Strategy and Template patterns
Strategy and Template patterns are similar in that they allow different implementations for a
fixed set of behaviors. Their intents are different, however.
Strategy is used to allow different implementations of an algorithm, or operation, to be
selected dynamically at run time. Typically, any common behavior is implemented in an
abstract class and concrete subclasses provide the behavior that differs. The client is
generally aware of the different strategies that are available and can choose between them.
For example, an abstract class, Sensor, could define taking measurements and concrete
subclasses would be required to implement different techniques: one might provide a running
average, another might provide an instantaneous measurement, and yet another might hold
a peak (or low) value for some period of time.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks

Java design patterns 101 Page 16 of 22
The intention of the Template pattern is not to allow behavior to be implemented in different
ways, as in Strategy, but rather to ensure that certain behaviors are implemented. In other
words, where the focus of Strategy is to allow variety, the focus of Template is to enforce
consistency.
The Template pattern is implemented as an abstract class and it is often used to provide a
blueprint or an outline for concrete subclasses. Sometimes this is used to implement hooks
in a system, such as an application framework.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 17 of 22
Section 7. Concurrency patterns
Overview
Concurrency patterns prescribe the way access to shared resources is coordinated or
sequenced. By far the most common concurrency pattern is Single Thread Execution, where
it must be ensured that only one thread has access to a section of code at a time. This
section of code is called a critical section, and typically it is a section of code that either
obtains access to a resource that must be shared, such as opening a port, or is a sequence
of operations that should be atomic, such as obtaining a value, performing calculations, and
then updating the value.
The Single Thread Execution pattern
The Singleton pattern we discussed earlier contains two good examples of the Single Thread
Execution pattern. The problem motivating this pattern first arises because this example uses
lazy instantiation delaying instantiating until necessary thereby creating the possibility
that two different threads may call getInstance() at the same time:
public static synchronized Sequence getInstance()
{
if(instance==null) // Lazy instantiation
{
instance = new Sequence();

}
return instance;
}
If this method were not protected against simultaneous access with synchronized, each
thread might enter the method, test and find that the static instance reference is null, and
each might try to create a new instance. The last thread to finish wins, overwriting the first
thread's reference. In this particular example, that might not be so bad it only creates an
orphaned object that garbage collector will eventually clean up but had there been a
shared resource that enforced single access, such as opening a port or opening a log file for
read/write access, the second thread's attempt to create an instance would have failed
because the first thread would have already obtained exclusive access to the shared
resource.
Another critical section of code in the Singleton example is the getNext() method:
public static synchronized int getNext()
{
return ++counter;
}
If this is not protected with synchronized, two threads calling it at the same time might
obtain the same current value and not the unique values this class is intended to provide. If
this were being used to obtain primary keys for a database insert, the second attempt to
insert with same primary key would fail.
As we discussed earlier, you should always consider the cost of using a pattern. Using
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 18 of 22
synchronized works by locking the section of code when it is entered by one thread and
blocking any other threads until the first thread is finished. If this is code used frequently by
many threads, this could cause a serious degradation in performance.
Another danger is that two threads could become deadlocked if one thread is blocked at one
critical section waiting for the second, while the second thread is blocked at another critical

section, waiting for the first.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 19 of 22
Section 8. Wrapup
Summary
Design patterns are a valuable tool for object-oriented design for a number of important
reasons:
* Patterns provide " a solution to a problem in a context." (Design Patterns, Gamma,
Helm, Johnson, and Vlissides).
* Patterns capture the expertise of experienced designers in a methodical way and make
them available as design tools and learning tool for non-experts.
* Patterns provide a vocabulary for discussing object-oriented design at a significant level
of abstraction.
* Patterns catalogs serve as a glossary of idioms that help in understanding common, but
complex solutions to design problems.
Resources
Books
* Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma,
Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley, 1995) is probably
the most influential resource on object-oriented design. Chapters 1, 2, and 6 are
essential reading for understanding object-oriented design in general or, in particular,
the role of patterns in object-oriented design.
* Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML by Mark
Grand (Wiley, 1998) is not as well written as Design Patterns, especially regarding
general object-oriented design issues, but the patterns in the catalog are easier to
understand, particularly because the examples are written using the Java language and
the recommendations address issues common for Java developers.
* Core J2EE Patterns: Best Practices and Design Strategies by Deepak Alur, John Crupi,
and Dan Malks (Prentice Hall, 2001) is a catalog of patterns for the design and

architecture of multitier enterprise applications.
* UML Distilled: Applying the Standard Object Modeling Language by Martin Fowler with
Kendall Scott (Addison-Wesley, 2000) offers an excellent introduction to the essentials
of UML. It includes a short but valuable discussion of using
Class-Responsibility-Collaboration cards for object-oriented design.
* The Unified Modeling Language User Guide by Grady Booch, Ivar Jacobson, and
James Rumbaugh (Addison-Wesley, 1998) is helpful when you need more than just the
essentials.
Web resources
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 20 of 22
* developerWorks has two good introductory articles on the Java programming language
and on object-oriented design in general:
* "The OO design process: Getting started" by Allen Holub
* "The object primer: Using object-oriented techniques to develop software" by
Scott W. Ambler
* There are also several articles on the Java language, patterns, and UML:
* "A UML workbook" (Part 1, Part 2, and Part 3) by Granville Miller
* "An overview of object relationships: The basics of UML and Java associations" by
Scott W. Ambler
* "Use your singletons wisely: Know when to use singletons, and when to leave
them behind" by J. B. Rainsberger
* "Developing Java solutions using Design Patterns" by Kelby Zordrager
* There are several Web sites with good information on patterns. The Hillside Group
plays a major role in the pattern community and its site, in particular, is an excellent
starting point:
* The Hillside Group Patterns home page
* Portland Pattern Repository
* Brad Appleton's Software Patterns Links

* "Christopher Alexander: An Introduction for Object-Oriented Designers" is an
interesting read for those wanting to learn more about the father of design patterns.
* The most discussed and dissected pattern, in this tutorial and elsewhere, is the
Singleton pattern. Here are two articles that cover the topic thoroughly from different
perspectives:
* "Implementing the Singleton Pattern in Java" by Rod Waldhoff
* "When is a singleton not a singleton?" by Joshua Fox
UML tools
* UML tools are of two types: those that provide CASE (Computer Aided Software
Engineering) and those that are only for creating diagrams. The CASE tools use UML
diagrams to generate code. They can also reverse-engineer code and generate
diagrams. Some people find these capabilities to be useful. Rational Rose and
Together/J are in this category, while ArgoUML and SmartDraw provide only drawing
capabilities:
* Rational Rose is an industrial-strength software design tool (and much more) that
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 21 of 22
strictly enforces its interpretation of UML. This can be frustrating if developers are
using it for conceptual or informal designs. It's expensive, but you can download a
15-day evaluation version to test out.
* Together/J is also an industrial-strength software design tool that enforces its
interpretation of UML. Download the free whiteboard version (which doesn't have
code-generation or round-trip engineering) for a test ride.
* ArgoUML is a free, Java language, open source, UML diagramming tool. It's much
smaller than Rational Rose or Together/J because it doesn't have the code
generation and other engineering tools, and it is significantly easier to use. Be
aware that the current version, 0.9.5 (as of December 2001), is beta and has
significant bugs.
* SmartDraw is an inexpensive general-purpose diagramming tool that includes

support for UML. Because it is designed as a general-purpose tool, it can be
awkward to use for UML. Don't miss the comprehensive UML tutorial from
SmartDraw.
Feedback
Please send us your feedback on this tutorial. We look forward to hearing from you!
Additionally, you are welcome to contact the author, David Gallardo, directly at

Colophon
This tutorial was written entirely in XML, using the developerWorks Toot-O-Matic tutorial
generator. The open source Toot-O-Matic tool is an XSLT stylesheet and several XSLT
extension functions that convert an XML file into a number of HTML pages, a zip file, JPEG
heading graphics, and two PDF files. Our ability to generate multiple text and binary formats
from a single source file illustrates the power and flexibility of XML. (It also saves our
production team a great deal of time and effort.)
You can get the source code for the Toot-O-Matic at
www6.software.ibm.com/dl/devworks/dw-tootomatic-p. The tutorial Building tutorials with the
Toot-O-Matic demonstrates how to use the Toot-O-Matic to create your own tutorials.
developerWorks also hosts a forum devoted to the Toot-O-Matic; it's available at
www-105.ibm.com/developerworks/xml_df.nsf/AllViewTemplate?OpenForm&RestrictToCategory=11.
We'd love to know what you think about the tool.
Presented by developerWorks, your source for great tutorials
ibm.com/developerWorks
Java design patterns 101 Page 22 of 22

×