Object Oriented Programs Session 6: Design Patterns

Reuse of Design: Design Patterns

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 Patterns

Structural Patterns

Behavioural Patterns

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:

 

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:

 

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...

               this.addWindowListener(new WindowAdaptor(){
                       public void windowClosing(WindowEvent e){
                               System.exit.(0);
                       }
               });
                       
               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,...

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:

Mary Martin | Dept CS&CE, Bendigo ©2007