Reuse of Design: Design Patterns
- Observation: Many problem solutions have similar structures
- Recognition of familiar structures in a problem leads to increased productivity and reliability of product!
- Design Patterns formalize the process of identifying the similarity and applying the same solution structure. They are generalized solutions to problems with the same structure.
- "The basic idea is to characterize the features of a proven solution to a small problem, summarizing the essential elements and omitting the unnecessary detail. " - Budd, p 245.
- "Design Patterns are recurring solutions to design problems you see over and over" - Smalltalk Companion
- Patterns can assist in solving new problems that have similarity to the problem solved by the design pattern.
Pattern Categories
The landmark book 'Design Patterns - Elements of Reusable Software" by Gamma, Helm, Johnson & Vlissides [1995] described 23 patterns and grouped them into three categories:
-
Creational: a pattern for creating Objects conditionally rather than instantiate them directly. It gives your program more flexibility.
-
Structural: a pattern for grouping groups of objects into a larger structure.
-
Behavorial: a pattern for defining the communication between objects in your program and how the flow is controlled in a complex program.
Creational Patterns
- Factory
- Abstract Factory
- Builder
- Singleton
- Prototype
Structural Patterns
Behavioural Patterns
- Strategy
- Observer
- Iterator
- Chain of Responsibility
- Memento
- Command
- Interpreter
- Mediator
- State
- Template
- Visitor
Some Creational Patterns:
Factory
Problem: You have a method that returns a newly created object, but you want subclasses to have the ability to return different types of object.
Solution: Allow the subclass to override the creation method and return a different type of object.
There are numerous examples in the Java API, egs:
-
The interface SocketImplFactory from the java.net package defines a factory for socket implementations. It is used by the classes Socket and ServerSocket to create actual socket implementations.
-
The class BorderFactory is a Factory class for standard Border objects.
- eg: setBorder(BorderFactory.createTitledBorder("Patient List"));
- Wherever possible, this factory will hand out references to shared Border instances (the Flyweight pattern).
- All method names begin with the word 'create'
-
The method clone() returns a copy of an object... provided the object implements the Clonable interface.
Abstract Factory
Problem: How to provide a mechanism for creating instances of families of related objects without specifying their concrete representations
Solution: Provide a method that returns a new value that is characterized only by an interface or parent class
egs:
- The class UIManager from the javax.swing package manages the multiple look
and feel user interfaces such as Windows, Motif (X Windows) and Macintosh,
eg:
-
String lafClass = UIManager.getSystemLookAndFeelClassName(); try{ UIManager.setLookAndFeel(lafClass); ...
-
- The collection classes Vector, Hashtable and Dictionary define a method named elements() that is described as returning a value
- of type Enumeration, i.e.
this Abstract Factory method produces an object. Successive
calls to the nextElement method
return successive elements of the series. For example, to print all elements
of a vector v:
for (Enumeration e = v.elements() ; e.hasMoreElements() ;) { System.out.println(e.nextElement()); }(NOTE from Java API: The functionality of this interface is duplicated by the Iterator interface. Iterator also adds an optional remove operation, and has shorter method names. New implementations should consider using Iterator in preference to Enumeration.)
Builder
Problem: How to present a GUI depending on the particular option selected
Solution: Assembles a number of objects to make a new object based on the data with which it is presented. Often the choice of which way the objects are assembled is achieved using a Factory pattern.
eg: Ward Management application. May want to see ward data (list of patients) or Patient data (details about the patient).
Singleton
Problem: How to ensure only a single object of the class is created and used by all other objects.
Solution: Define a class that creates a single instance of an object of that class and provides a method to get that intstance. The constructor is declared private so that only the class itself can create an object of itself! Eg a random number generator to share.
Some Structural Patterns:
Adapter
Problem: How to use an object that provides appropriate behaviour but used a different interface, eg difference in US and Aussie appliance power voltages.
Solution: Use an Adaptor! ...in software create a class that acts as an adaptor (intermediary).
No extra functionality is provided...just makes the object usable or easier to use.
egs...
- 1. In AWT, MouseAdaptor, WindowAdaptor implement the Listener classes...in application class
this.addWindowListener(new WindowAdaptor(){
public void windowClosing(WindowEvent e){
System.exit.(0);
}
});
- 2. wrapper classes for fundamental data types
Integer theInt = new Integer(12);
Composition
Problem: creation of complex object from simple components
Solution: provide a collection of simple components which can be nested arbitrarily...
eg...
AWT component and container classes
Checkbox, Choice, List, Button,
Canvas, Label Scrollbar, TextComponent
MenuBar, MenuItem, Menu etc
are Component or MenuComponent classes
Frame, Dialog, FileDialog, Panel, ScrollPane
are Container classes as well
By nesting panels within one another, complex layouts can often be created. The `is a' and `has a' relationships often become merged, eg
a container `has a' layout manager and inherits `is a' a component
Flyweight
Problem: How to reduce the storage of a large number of similar state objects?
Solution: Share state in common with similar objects
eg...
All objects in Java are an instance of some class. Each class must have some identifying info (eg, name of class). This into is defined once by an object of type Class and each instance of the class points to this single copy of the info.
Decorator (Filter or Wrapper)
Problem: How to attach additional responsibilities (functionality) to an object dynamically
Solution: By combining `is a' and `has a' relations, create an object that wraps around an existing value, adding new behaviour without changing the interface
eg...
The object of class InputStream reads bytes from an input stream. The class BufferedInputStream is a subclass of InputStream adding the ability to buffer the input so that it can be reset to an earlier point and values can be reread. An object of type BufferedInputStream takes InputStream as an argument in its constructor... It `is a' InputStream object (because it is subclassed from InputStream) and it `has a' InputStream object as part of its data.
Proxy
Problem: How do you hide details such as transmission protocols to remote objects?
Solution: Provide a proxy that acts as a surrogate or placeholder for another object
eg...
The RMI (Remote Method Invocation) system that allows communication between java programs running on two or more machines... RMI creates a proxy object that runs on the same machine as the client. When the client invokes a method on the proxy, the proxy transmits the method across the network to the server on another machine. The server handles the request and sends the result back to the proxy. The proxy hands the result back to the client. The proxy and the server do the hard work!
eg2... (to avoid downloading images until they are needed)
In this example, only the currently selected tabbed panel content displays so image loading can be deferred until its panel is selected. Instead of adding ImageIcon objects to the JLabel objects, a proxy object is provided to the label. The ImageProxy class implements the Icon interface type (like ImageIcon). Its paintIcon method ensures that the image is loaded when needed and then passes the request onto the actual image object.
(Put your own images in a subdirectory called images to test the following code, and modify the code to reflect your image file names.)
ProxyPatternEg.java
ImageProxy.java
Bridge
Problem: How to decouple an abstraction from its implementation so that the latter can vary independently... i.e., separation of independent from the dependent.
Solution: Remove the implementation details from the abstraction, placing them instead in an object that is held as a component in the abstraction.
eg...
Most of the AWT component classes...eg, the platform independent details of the button component class are stored in the class Button and the platform dependent details are stored in the ButtonPeer class which the Button object maintains.
Unlike the strategy class the average Java programmer usually does not need to know about the dependent classes and they are usually not visible.
Some Behavorial Patterns
Strategy
Problem: How do you allow the algorithm that is used to solve a particular problem to be easily and dynamically changed by the client?
Solution: Define a family of algorithms with a similar interface. Encapsulate each algorithm and let the client (user) select the strategy.
eg...
The AWT layout managers: the details of how items are laid out on the screen are left to the layout manager. An interface is defined and five standard layouts are provided... and the programmer can even define a new one if desired!
Observer
Problem: How do you control two or more independently coupled objects to change in synchrony with each other?
Solution: Maintain a list of objects that are tied, or dependent on another object - often called the Model - View approach. When the object (Model) changes the dependents (observers) are notified and update themselves
egs,...
- 1. AWT GUI components that allow interaction maintain a list of listener objects. When the action occurs the listeners are notified and implement the update or action.
- 2. The class Observable allows classes to be made `observable' by extending.Other
Objects which want to observe the observable object implement the interface
Observer (These correspond to `listener' objects.)
The observable object implements a method to notify the observers... the observers implement an update method which takes the observable object as an argument.
Iterator
Problem: How to provide a way to access elements of an aggregate object (eg array) sequentially without exposing the underlying representation.
Solution: Provide a mediator object for the sole purpose of sequential access. The mediator object can be aware of the representation but the user of the object need not be.
eg.Java has the Enumeration interface... and since Java 1.2 the Iterator interface. Iterator takes the place of Enumeration in the Java collections framework. Iterators differ from enumerations in two ways:
- Iterators allow the caller to remove elements from the underlying collection
during the iteration, eg:
- remove() : Removes from the list the last element that was returned by next or previous .
- set(Object o) : Replaces the last element returned by next or previous with the specified element.
- Method names have been improved.