Resources

back to Design Patterns Explained book support page

Below are code fragments used in the book, organized by chapter


Chapter 1: The Object-Oriented Paradigm

For example, in Step 4c on page 4, where I "Call the appropriate function that will display the shape, giving it the shape's location," I could write a module like that shown in Example 1-1.

Example 1-1 Using Modularity to Contain Variation

function: display shape
input: type of shape, description of shape
action:
switch (type of shape)
case square: put display function for square here
case circle: put display function for circle here

Chapter 2: The UML - The Unified Modeling Language

No code fragments


Chapter 3: A Problem That Cries Out for Flexible Code

No code fragments


Chapter 4: A Standard Object-Oriented Solution

Example 4-1 Java Code Fragments: Instantiating the V1 Features

// segment of code that instantiates the features
// no error checking provided--for illustration
// purposes only
public class V1Model extends Model {
static public Model buildV1Model (String modelName) {
V1Model myModel= new V1Model();
myModel.modelNumber= myModel.openModel( modelName);
		if (myModel.modelNumber <= 0) return null;
myModel.buildModel();
return myModel;
}
private void buildModel () {
// each feature object needs to know the model number 
// and feature ID it corresponds to in order to
// retrieve information when requested. Note how
// this information is passed to each object's
// constructor
nElements= getNumberOfElements();
features= new Feature[ nElements];
// do for each feature in the model
int i;
int ID;
for (i= 0; i < nElements; i++) {
	// determine feature present and create 
// appropriate feature object
	ID= V1.getFeatureID( modelNumber, i);
	switch( V1.getFeatureType( modelNumber, ID)) {
case FEATURE_SLOT:
features[i]= new V1Slot( modelNumber, ID);
break;
		case FEATURE_HOLE:
features[i]= new V1Hole( modelNumber, ID);
break;
		// Other cases
		}
	}
}
}

Example 4-2 Java Code Fragments: Implementation of V1 Methods


// myModelNumber and myID are private members containing
// information about the model and feature (in V1) this 
// feature corresponds to
public class V1Slot extends SlotFeature {
. . .
public double getX1 () {
return V1.getX1forSlot( myModelNumber, myID);
}
public double getX2 () {
return V1.getX2forSlot( myModelNumber, myID);
}
}
public class V1Hole extends HoleFeature {
. . .
public double getXLoc () {
return V1.getXforHole( myModelNumber, myID);
} 
}

Example 4-3 Java Code Fragments: Instantiating the V2 Features



// segment of code that instantiates the features
// no error checking provided--for illustration 
// purposes only
public class V2Model extends Model {
static public Model buildV2Model (String modelName) {
// open model
V2Model myModel= new V2Model();
if (!myModel.openModel( modelName)) return null;
myModel.buildModel();
return myModel;
}
private void buildModel () {
// each feature object needs to know the feature in the 
// V2 system it corresponds to in order to retrieve 
// information when requested. Note how this information
// is passed into each object's constructor
nElements= getNumberOfElements();
OOGFeature oogF;
// do for each feature in the model
int i;
for (i= 0; i < nElements; i++) {
// determine feature present and create 
// appropriate feature object
oogF= getElement(i);
switch( oogF.getType()) {
case OOG_SLOT:
features[i]= new V2Slot( oogF);
break;
case OOG_HOLE:
features[i]= new V2Hole( oogF);
break;
// other cases
}
}
}
}

Example 4-4 Java Code Fragments: Implementation of V2 Methods


// oogF is a reference to the feature object in V2 that

// the object containing it corresponds to

public class V2Slot extends SlotFeature {

. . .

public double getX1 () throws Exception {

// call appropriate method on oogF to

// get needed information.

return myOogF.getX1Loc();

}

public double getX2 () throws Exception {

// call appropriate method on oogF to

// get needed information.

return myOogF.getX2Loc();

}

}

public class V2Hole extends HoleFeature {

. . .

public double getXLoc () throws Exception {

// call appropriate method on oogF to

// get needed information.

return myOogF.getXLoc();

}

}

top


Chapter 5: An Introduction to Design Patterns

No code fragments

top


Chapter 6: The Façade Pattern

 No code fragments

top


Chapter 7: The Adapter Pattern

An example of wrapping is shown in Example 7-1.

Example 7-1 Java Code Fragments: Implementing the Adapter Pattern



class Circle extends Shape {
...
private XXCircle myXXCircle;
...
public Circle () { 
myXXCircle= new XXCircle(); 
}
void public display() {
myXXCircle.displayIt();
}
...
}

top


 Chapter 8: Expanding Our Horizons

No code fragments

top


Chapter 9: The Strategy Pattern

Switches, etc.
// Handle Tax
switch (myNation) {
case US:
// US Tax rules here
break;
case Canada:
// Canadian Tax rules here
break;
}
// Handle Currency
switch (myNation) {
case US:
// US Currency rules here
break;
case Canada:
// Canadian Currency rules
// here
break;
}

// Handle Date Format
switch (myNation) {
case US:
// use mm/dd/yy format
break;
case Canada:
// use dd/mm/yy format
break;
}

But what happens when there are more variations? For example, suppose I need to add Germany to the list of countries and also add language as a result. Now, the code looks like this:

// Handle Tax
switch (myNation) {
case US:
// US Tax rules here
break;
case Canada:
// Canadian Tax rules here
break;
case Germany:
// Germany Tax rules here
break;
}
// Handle Currency
switch (myNation) {
case US:
// US Currency rules here
break;
case Canada:
// Canadian Currency rules
// here
break;
case Germany:
// Euro Currency rules here
break;
}

// Handle Date Format
switch (myNation) {
case US:
// use mm/dd/yy format
break;
case Canada:
case Germany:
// use dd/mm/yy format
break;
}
// Handle Language
switch (myNation) {
case US:
case Canada:
// use English
break;
case Germany:
// use German
break;
}

This still is not too bad, but notice how the switches are not quite as nice as they used to be. There are now fall-throughs. But then I need to start adding variations within a case. Suddenly, things get bad in a hurry. For example, to add French in Quebec, my code looks like this:

// Handle Language
switch (myNation) {
case Canada:
if ( inQuebec) {
// use French
break;
}
case US:
// use English
break;
case Germany:
// use German
break;
}

Step 2: Favor aggregation

Example 9-1 Java Code Fragments: Implementing the Strategy Pattern

public class TaskController {
public void process () {
// this code is an emulation of a 
// processing task controller
// . . .
// figure out which country you are in
CalcTax myTax;
myTax= getTaxRulesForCountry();
SalesOrder mySO= new SalesOrder();
mySO.process( myTax);
}
private CalcTax getTaxRulesForCountry() {
// In real life, get the tax rules based on
// country you are in. You may have the
// logic here or you may have it in a
// configuration file
// Here, just return a USTax so this 
// will compile.
return new USTax();
}
}
public class SalesOrder {
public void process (CalcTax taxToUse) {
long itemNumber= 0;
double price= 0;
// given the tax object to use
// . . .
// calculate tax
double tax= 
taxToUse.taxAmount( itemNumber, price);
}
}
public abstract class CalcTax {
abstract public double taxAmount( 
long itemSold, double price);
}
public class CanTax extends CalcTax {
public double taxAmount( 
long itemSold, double price) {
// in real life, figure out tax according to
// the rules in Canada and return it
// here, return 0 so this will compile
return 0.0;
}
}
public class USTax extends CalcTax {
public double taxAmount( 
long itemSold, double price) {
// in real life, figure out tax according to
// the rules in the US and return it
// here, return 0 so this will compile
return 0.0;
}
}

top


Chapter 10: The Bridge Pattern


Proper use of inheritance

Example 10-1 Java Code Fragments

abstract public class Rectangle {
private double _x1, _y1, _x2, _y2;
public Rectangle 
(double x1, double y1, double x2, double y2) {
x1= x1; _y1= y1; _x2= x2; _y2= y2;
}
public void draw() {
drawLine( _x1, _y1, _x2, _y1);
drawLine( _x2, _y1, _x2, _y2);
drawLine( _x2, _y2, _x1, _y2);
drawLine( _x1, _y2, _x1, _y1);
}
abstract protected void drawLine
(double x1, double y1, double x2, double y2);
}

Designing with inheritance

Example 10-2 Java Code Fragments

abstract class Shape {
abstract public void draw();
}
// the only change to Rectangle is
abstract class Rectangle extends Shape { 
//
// V1Rectangle and V2Rectangle don't change
abstract public class Circle extends Shape {
protected double _x, _y, _r;
public Circle (double x, double y, double r) {
_x= x; _y= y; _r= r;
}
public void draw() {
drawCircle();
}
abstract protected void drawCircle();
}
public class V1Circle extends Circle {
public V1Circle 
(double x, double y, double r) {
super(x,y,r);
}
protected void drawCircle () {
DP1.draw_a_circle( _x, _y, _r);
}
}
public class V2Circle extends Circle {
public V2Circle(double x, double y, double r) {
super( x, y, r);
}
protected void drawCircle () {
DP2.drawCircle( _x, _y, _r);
}
}

Relating this to the inheritance-based design

Example 10-3 Java Code Fragments


public class Client {
static public void main () {
Shape myShapes[];
Factory myFactory= new Factory();
// get rectangles from some other source
myShapes= myFactory.getShapes();
for (int i= 0; i < myShapes.length; i++) {
myShapes[i].draw();
}
}
}
abstract public class Shape {
protected Drawing myDrawing;
abstract public void draw();
Shape (Drawing drawing) {
myDrawing= drawing;
}
protected void drawLine (
double x1,double y1, double x2,double y2) {
myDrawing.drawLine(x1,y1,x2,y2);
}
protected void drawCircle (
double x,double y,double r) {
myDrawing.drawCircle(x,y,r);
}
}
public class Rectangle extends Shape {
private double _x1, _y1, _x2, _y2;
public Rectangle (Drawing dp, double x1, 
double y1, double x2, double y2) {
super( dp);
x1= x1; _y1= y1; _x2= x2; _y2= y2;
}
public void draw() {
drawLine( _x1, _y1, _x2, _y1);
drawLine( _x2, _y1, _x2, _y2);
drawLine( _x2, _y2, _x1, _y2);
drawLine( _x1, _y2, _x1, _y1);
}
protected void drawLine(double x1, double y1,
double x2, double y2) {
myDrawing.drawLine( x1, y1, x2, y2);
}
}
public class Circle extends Shape {
private double _x, _y, _r;
public Circle (Drawing dp, 
double x, double y, double r) {
super(dp);
x= x; _y= y; _r= r;
}
public void draw() {
myDrawing.drawCircle( _x, _y, _r);
}
}
abstract public class Drawing {
abstract public void drawLine(double x1, 
double y1, double x2, double y2);
abstract public void drawCircle( 
double x, double y, double r);
}
public class V1Drawing extends Drawing {
public void drawLine (
double x1,double y1, 
double x2,double y2) {
DP1.draw_a_line(x1,y1,x2,y2);
}
public void drawCircle (
double x,double y,double r) {
DP1.draw_a_circle(x,y,r);
}
}
public class V2Drawing extends Drawing {
public void drawLine (
double x1,double y1, 
double x2,double y2) {
// arguments are different in DP2
// and must be rearranged
DP2.drawLine(x1,x2,y1,y2);
}
public void drawCircle (
double x, double y,double r) {
DP2.drawCircle(x,y,r);
}
}

top


Chapter 11: The Abstract Factory Pattern

Example 11-1 Java Code Fragments: A Switch to Control Which Driver to Use

// JAVA CODE FRAGMENT
class ApControl {
. . .
public void doDraw() {
. . .
switch (RESOLUTION) {
case LOW:
// use lrdd
case HIGH:
// use hrdd
}
}
public void doPrint() {
. . .
switch (RESOLUTION) {
case LOW:
// use lrpd
case HIGH:
// use hrpd
}
}
}

Example 11-2 Java Code Fragments: Using Polymorphism to Solve the Problem



// JAVA CODE FRAGMENT
class ApControl {
. . .
public void doDraw() {
. . .
myDisplayDriver.draw();
}
public void doPrint() {
. . .
myPrintDriver.print();
}
}
Example 11-3 Java Code Fragments: Implementation of ResFactory

abstract class ResFactory {
abstract public DisplayDriver getDispDrvr();
abstract public PrintDriver getPrtDrvr();
}
class LowResFact extends ResFactory {
public DisplayDriver getDispDrvr() {
return new LRDD();
}
public PrintDriver getPrtDrvr() {
return new LRPD();
}
}
class HighResFact extends ResFactory {
public DisplayDriver getDispDrvr() {
return new HRDD();
}
public PrintDriver getPrtDrvr() {
return new HRPD();
}
}

top


Chapter 12: How Do Experts Design?

No code fragments

top


Chapter 13: Solving The CAD/CAM Problem with Patterns

No code fragment

top


Chapter 14: The Principles and Strategies of Design Patterns

No code fragments

top


Chapter 15: Commonality and Variability Analysis (CVA)

No code fragments

top


Chapter 16: The Analysis Matrix

No code fragments

top


Chapter 17: The Decorator Pattern

How it works: Decorators wrap their trailing object

Example 17-1 Java Code Fragment: Decorator

public class Client {
public static void main( String[] args) {
Factory myFactory;
myFactory= new Factory();
Component myComponent= 
myFactory.getComponent();
}
}
abstract public class Component {
abstract public void prtTicket();
}
public class SalesTicket extends Component {
public void prtTicket() {
// place sales ticket printing code here
}
}
abstract public class TicketDecorator extends Component {
private Component myTrailer;
public TicketDecorator (Component myComponent) {
myTrailer= myComponent;
}
public void callTrailer () {
if (myTrailer != null) myTrailer.prtTicket();
}
}
public class Header1 extends TicketDecorator {
public Header1 (Component myComponent) {
super( myComponent);
}
public void prtTicket () {
// place printing header 1 code here
super.callTrailer(); 
}
}
public class Header2 extends TicketDecorator {
public Header2 (Component myComponent) {
super( myComponent);
}
public void prtTicket () {
// place printing header 2 code here
super.callTrailer(); 
}
}
public class Footer1 extends TicketDecorator {
public Footer1 ( Component myComponent) {
super( myComponent);
}
public void prtTicket() {
super.callTrailer();
// place printing footer 1 code here
}
}
public class Footer2 extends TicketDecorator {
public Footer2 ( Component myComponent) {
super( myComponent);
}
public void prtTicket() {
super.callTrailer();
// place printing footer 2 code here
}
}
public class Factory {
public Component getComponent () {
Component myComponent;
myComponent= new SalesTicket();
myComponent= new Footer1( myComponent);
myComponent= new Header1( myComponent);
return myComponent;
}
}

What happens in the code

If I want the sales ticket to look like:

HEADER 1
SALES TICKET
FOOTER 1
Then myFactory.getComponent returns
return( new Header1( new Footer1 ( new SalesTicket())));

This creates a Header1 object trailed by a Footer1 object trailed by a SalesTicket object.

If I want the sales ticket to look like:

HEADER 1
HEADER 2
SALES TICKET
FOOTER 1
Then myFactory.getComponent returns
return( new Header1( new Header2 (new Footer1( 
new SalesTicket()))));

This creates a Header1 object trailed by a Header2 object trailed by a Footer1 object trailed by a SalesTicket object.

top


Chapter 18: The Observer Pattern

The Observer pattern aids flexibility and keeps things decoupled

Example 18-1 Java Code Fragment: Observer Implemented

// Note: I don't use the Java Observer or Observable. 
// In practice they give me little assistance and I 
// don't like their interfaces.
import java.util.*;
public class Customer {
static private Vector myObs;
static {
myObs= new Vector();
}
public static void attach(MyObserver o){
myObs.addElement(o);
}
public static void detach(MyObserver o){
myObs.remove(o);
}
public String getState () {
// have other methods that will give the 
// required information
// Here, just return null so this will compile 
return null;
}
public void notifyObs () {
// set arg to something that helps
// tell the Observers what happened
for (Enumeration e = myObs.elements(); 
e.hasMoreElements() ;) {
((MyObserver) e).update(this);
}
}
}
interface MyObserver {
void update (Customer myCust);
}
class AddrVerification implements MyObserver {
public AddrVerification () {
}
public void update ( Customer myCust) {
// do Address verification stuff here
// can get more information about customer
// in question by using myCust
}
}
class WelcomeLetter implements MyObserver {
public WelcomeLetter () {
}
public void update (Customer myCust) {
// do Welcome Letter stuff 
// here can get more 
// information about customer 
// in question by using myCust
}
}

top

Chapter 19: The Template Method Pattern

No code fragments

top


Chapter 20: Lessons from Design Patterns: Factories

No code fragments

top


Chapter 21: The Singleton Pattern and the Double-Checked Locking Pattern

Singleton makes objects responsible for themselves

The Singleton could be implemented in code as shown in Example 21-1. In this example, I create a method (getInstance) that will instantiate at most one USTax object. The Singleton protects against someone else instantiating the USTax object directly by making the constructor private, which means that no other object can access it.

Example 21-1 Java Code Fragment: Singleton Pattern

public class USTax extends Tax {
private static USTax instance;
private USTax() { }
public static USTax getInstance() {
if (instance== null) instance= new USTax();
return instance;
}
}

Singleton with polymorphism

Example 21-2 Java Code Fragment: Singleton Pattern in the context of the e-commerce system.

abstract public class Tax {
static private Tax instance;
protected Tax() { };
abstract double calcTax( 
double qty, double price);
public static Tax getInstance() {
// use whatever rule you use to determine
// which tax object to use. For now, 
// let's create a USTax object.
instance= USTax.getInstance();
return instance;
}
}
public class USTax extends Tax {
private static USTax instance;
private USTax() { }
// Note in the following, I had to change USTax 
// to Tax since I used the same "getInstance" 
// name.
public static Tax getInstance() {
if (instance== null) instance= new USTax();
return instance;
}
}

A simple solution: double-checked locking

Example 21-3 Java Code Fragment: Instantiation Only

public class USTax extends Tax {
private static USTax instance;
private USTax() { }
public static Tax getInstance() {
if (instance== null) { 
synchronized(this) {
if (instance == null) 
instance = new USTax();
}
}
return instance;
}
private synchronized static void doSync() {
if (instance == null)instance = new USTax();
}
}

A Solution for Java

It is not all that hard to fix this - not that I figured it out on my own. One solution is to take advantage of the class loader, as shown in Example 21-4.

Example 21-4 Java Code Fragment: Instantiation Only

public class USTax extends Tax {
private static class Instance {
static final Tax instance= new USTax();
}
private static USTax instance;
private USTax() { }
public static Tax getInstance() {
return Instance.instance;
}
}

top


Chapter 22: The Object Pool Pattern

No code fragments

top


Chapter 23: The Factory Method Pattern

No code fragments

top


Chapter 24: Summary of Factories

No code fragment

top


Chapter 25: Design Patterns Reviewed From Our New Perspective of Object-Oriented Principles

No code fragments

top

Sample Podcast

Lean and What do we do next? - Part 2
Presenter's photo January 25th, 2007
Author: Jim Trott

These Lean-Agile principles all seem reasonable, but abstract. What do we do to put it into practice? This is part 2 of a discussion on this.

Free Registration Gets You More!

Register for a free Net Objectives account, and you'll gain access to much more content: more Streamzines, more Ezines, our bibliographies and FAQ's, and all the preparatory material we recommend to anyone planning to take a Net Objectives course.

Why Register? Register Now