Thinking in Patterns by Bruce Eckel
Revision 0.9, 5-20-2003 (This version contains the material that will be used in the Crested Butte seminar; see http://www.mindview.net/Seminars/ThinkingInPatterns/)
Please note this document is under development and incomplete. Updates to this document can be found at http://www.Mindview.net

Best viewed with Mozilla! (free at www.Mozilla.org) (Even though this document was created with MS Word, IE6 garbles lines with superscripts on them. Mozilla seems to do a much better job).

___________________________________________

Note: This document requires the installation of the fonts Georgia, Verdana and Andale Mono (code font) for proper viewing. These can be found at: http://sourceforge.net/project/showfiles.php?group_id=34153&release_id=105355

Modifications in Revision 0.9:

·         Prose has still had little/no work. My current goal is to get the structure and examples worked out so that the seminar works well. Once it has been proven in the seminars, then I will spend time on the prose.

·         Added proxy:PoolManager.java to make a more generic/customizeable Pool Manager, and modified proxy:ConnectionPoolProxyDemo.java accordingly [[ Still need to decide what to return when you run out of objects in the pool ]]

·         Changed PoolManager.java to use an ArrayList (and thus does not require a fixed size at initialization)

·         Added KissingPrincess.java to State description, as a motivational example for the pattern

·         Added a simple Flyweight example

·         Simplified the enumeration in PaperScissorsRock.java

Modifications in Revision 0.8:

·         Changed Bridge example to improve clarity.

·         Removed superscripts for better viewing with IE (see note above)

Modifications in Revision 0.7:

·         NOTE primary changes have been made to structure of book and code examples, but not to prose. Prose can be considered to be mostly a mess in this revision.

·         Complete reorganization under headings that attempt to describe the problems you are trying to solve with a pattern.

·         Addition of placeholders for the remainder of the GoF patterns

·         Addition of “Simplifying Idioms” section and examples

·         Addition of Builder section and examples

·         Removed unit-testing chapter; replaced with reference to “new” JUnit (which uses reflection)

·         (4-30-2003) Added Ant build.xml files, and support files from TIJ necessary to do a full standalone build. You should be able to type “ant” from the code root directory and get a successful build.

·         Dramatically simplified chainofresponsibility:FindMinima.java

·         Added object pool/connection pool examples

·         Refactored small things in many examples

·         Some exercises may have been left behind when patterns were moved.

·         For simplicity, saved from Word into a single HTML document, using “filtered” version to remove Office stuff. Seems to work pretty well; checked it with both IE and Mozilla (actually seems to work better on Mozilla than on IE!).

TODO:

·         Reconfigure for new backtalk system

·         Replace references to TIJ2 with TIJ3


Thinking

in

Patterns

Problem-Solving  Techniques using Java

Bruce Eckel

President, MindView, Inc.

#[BT_1]#


Contents

Preface  8

Introduction  11

The Y2K syndrome. 11

Context and composition. 12

A word about checked exceptions  13

The pattern concept 15

What is a pattern?. 15

Pattern taxonomy. 17

Design principles. 18

Classifying patterns. 19

The development challenge. 21

Unit testing. 21

Location of test code. 22

Simplifying Idioms  22

Messenger. 22

Collecting Parameter. 24

Object quantity  25

Singleton. 25

Exercises. 27

Object pool 27

Exercises. 30

Object decoupling  30

Proxy: fronting for another object 31

The PoolManager using Proxy. 33

Dynamic Proxies. 36

State: changing object behavior  38

Iterators: decoupling algorithms from containers  44

Type-safe iterators. 45

Exercises. 46

Factoring commonality  47

Strategy: choosing the algorithm at run-time  48

Policy: generalized strategy. 50

Template method. 50

Exercises. 52

Encapsulating creation  52

Simple Factory method. 53

Polymorphic factories. 55

Abstract factories. 58

Exercises. 61

Specialized creation  61

Prototype. 61

Builder. 62

Exercises. 66

Too many  66

Flyweight: too many objects. 66

Decorator: too many classes. 69

Basic decorator structure. 70

A coffee example. 70

Class for each combination. 70

The decorator approach. 73

Compromise. 78

Other considerations. 82

Exercises. 83

Connecting different types  84

Adapter. 84

Bridge. 87

Exercises. 93

Flexible structure  93

Composite. 93

System decoupling  95

Observer. 95

Observing flowers. 97

A visual example of observers. 101

Mediator. 103

Exercises. 104

Reducing interface complexity  104

Façade. 105

Package as a variation of Façade  106

Algorithmic partitioning  106

Command: choosing the operation at run-time  106

Exercises. 109

Chain of responsibility. 109

Exercises. 112

Externalizing object state  113

Memento. 113

Complex interactions  114

Multiple dispatching. 114

Visitor, a type of multiple dispatching  117

Exercises. 119

Multiple languages  120

Interpreter motivation. 121

Python overview.. 122

Built-in containers. 123

Functions. 124

Strings. 125

Classes. 127

Creating a language. 130

Controlling the interpreter. 134

Putting data in. 134

Getting data out. 140

Multiple interpreters. 143

Controlling Java from Jython  144

Inner Classes. 148

Using Java libraries. 148

Inheriting from Java library classes  150

Creating Java classes with Jython  151

Building the Java classes from the Python code  156

The Java-Python Extension (JPE)  157

Summary. 157

Exercises. 158

Complex system states  159

StateMachine. 159

Exercises. 169

Table-Driven State Machine. 169

The State class. 171

Conditions for transition. 172

Transition actions. 172

The table. 172

The basic machine. 173

Simple vending machine. 174

Testing the machine. 179

Tools. 180

Table-driven code: configuration flexibility  180

Table-driven code using anonymous inner classes  180

Exercises. 180

Pattern refactoring  181

Simulating the trash recycler. 182

Improving the design. 186

“Make more objects”. 186

A pattern for prototyping creation  189

Trash subclasses. 193

Parsing Trash from an external file  195

Recycling with prototyping. 198

Abstracting usage. 199

Multiple dispatching. 203

Implementing the double dispatch   204

The Visitor pattern. 211

A Reflective Decorator. 214

More coupling?. 219

RTTI considered harmful?. 220

Summary. 223

Exercises. 224

Projects  225

Rats & Mazes. 225

Other maze resources. 230

XML Decorator. 230

A: Tools  230

Ant extensions. 231

Array utilities. 232


Preface

The material in this book has been developed in conjunction with a seminar that I have given for several years, mostly with Bill Venners. Bill and I have given many iterations of this seminar and we’ve changed it many times over the years as we both have learned more about patterns and about giving the seminar.

In the process we’ve both produced more than enough information for us each to have our own seminars, an urge that we’ve both strongly resisted because we have so much fun giving the seminar together. We’ve given the seminar in numerous places in the US, as well as in Prague (where we try to have a mini-conference every Spring together with a number of other seminars). We’ve also given it as an on-site seminar.

A great deal of appreciation goes to the people who have participated in these seminars over the years, as they have helped me work through these ideas and to refine them. I hope to be able to continue to form and develop these kinds of ideas through this book and seminar for many years to come.

This book will not stop here, either. After much pondering, I’ve realized that I want Thinking in Python to be, initially, a translation of this book rather than an introduction to Python (there are already plenty of fine introductions to that superb language). I find this prospect to be much more exciting than the idea of struggling through another language tutorial (my apologies to those who were hoping for that).


#[BT_2]#


Introduction

This is a book about design that I have been working on for years, basically ever since I first started trying to read Design Patterns (Gamma, Helm, Johnson & Vlissides, Addison-Wesley, 1995), commonly referred to as the Gang of Four[1] or just GoF).

There is a chapter on design patterns in the first edition of Thinking in C++, which has evolved in Volume 2 of the second edition of Thinking in C++, and you’ll also find a chapter on patterns in the first edition of Thinking in Java (I took it out of the second edition because that book was getting too big, and also because I had decided to write this book).

This is not an introductory book. I am assuming that you have worked your way through Thinking in Java or an equivalent text before coming to this book.

In addition, I assume you have more than just a grasp of the syntax of Java. You should have a good understanding of objects and what they’re about, including polymorphism. Again, these are topics covered in Thinking in Java.

On the other hand, by going through this book you’re going to learn a lot about object-oriented programming by seeing objects used in many different situations. If your knowledge of objects is rudimentary, it will get much stronger in the process of understanding the designs in this book.

The Y2K syndrome

In a book that has “problem-solving techniques” in its subtitle, it’s worth mentioning one of the biggest pitfalls in programming: premature optimization. Every time I bring this concept forward, virtually everyone agrees to it. Also, everyone seems to reserve in their own mind a special case “except for this thing that I happen to know is a particular problem.”

The reason I call this the Y2K syndrome has to do with that special knowledge. Computers are a mystery to most people, so when someone announced that those silly computer programmers had forgotten to put in enough digits to hold dates past the year 1999, then suddenly everyone became a computer expert – “these things aren’t so difficult after all, if I can see such an obvious problem.” For example, my background was originally in computer engineering, and I started out by programming embedded systems. As a result, I know that many embedded systems have no idea what the date or time is, and even if they do that data often isn’t used in any important calculations. And yet I was told in no uncertain terms that all the embedded systems were going to crash on January 1, 2000. As far as I can tell the only memory that was lost on that particular date was that of the people who were predicting doom – it’s as if they had never said any of that stuff.

The point is that it’s very easy to fall into a habit of thinking that the particular algorithm or piece of code that you happen to partly or thoroughly understand is naturally going to be the bottleneck in your system, simply because you can imagine what’s going on in that piece of code and so you think that it must somehow be much less efficient than all the other pieces of code that you don’t know about. But unless you’ve run actual tests, typically with a profiler, you can’t really know what’s going on. And even if you are right, that a piece of code is very inefficient, remember that most programs spend something like 90% of their time in less than 10% of the code in the program, so unless the piece of code you’re thinking about happens to fall into that 10% it isn’t going to be important.

“We should forget about small efficiencies, say about 97% of the time: Premature optimization is the root of all evil.”—Donald Knuth

Context and composition

One of the terms you will see used over and over in design patterns literature is context. In fact, one common definition of a design pattern is “a solution to a problem in a context.” The GoF patterns often have a “context object” that the client programmer interacts with. At one point it occurred to me that such objects seemed to dominate the landscape of many patterns, and so I began asking what they were about.

The context object often acts as a little façade to hide the complexity of the rest of the pattern, and in addition it will often be the controller that manages the operation of the pattern. Initially, it seemed to me that these were not really essential to the implementation, use and understanding of the pattern. However, I remembered one of the more dramatic statements made in the GoF: “prefer composition to inheritance.” The context object allows you to use the pattern in a composition, and that may be it’s primary value.

A word about checked exceptions

1) The great value of exceptions is the unification of error reporting: a standard mechanism by which to report errors, rather than the popourri of ignorable approaches that we had in C (and thus, C++, which only adds exceptions to the mix, and doesn't make it the exclusive approach). The big advantage Java has over C++ is that exceptions are the only way to report errors.

2) "Ignorable" in the previous paragraph is the other issue. The theory is that if the compiler forces the programmer to either handle the exception or pass it on in an exception specification, then the programmer's attention will always be brought back to the possibility of errors and they will thus properly take care of them. I think the problem is that this is an untested assumption we're making as language designers that falls into the field of psychology. My theory is that when someone is trying to do something and you are constantly prodding them with annoyances, they will use the quickest device available to make those annoyances go away so they can get their thing done, perhaps assuming they'll go back and take out the device later. I discovered I had done this in the first edition of Thinking in Java:

...

} catch (SomeKindOfException e) {}

 

And then more or less forgot it until the rewrite. How many people thought this was a good example and followed it? Martin Fowler began seeing the same kind of code, and realized people were stubbing out exceptions and then they were disappearing. The overhead of checked exceptions was having the opposite effect of what was intended, something that can happen when you experiment (and I now believe that checked exceptions were an experiment based on what someone thought was a good idea, and which I believed was a good idea until recently).

When I started using Python, all the exceptions appeared, none were accidentally "disappeared." If you *want* to catch an exception, you can, but you aren't forced to write reams of code all the time just to be passing the exceptions around. They go up to where you want to catch them, or they go all the way out if you forget (and thus they remind you) but they don't vanish, which is the worst of all possible cases. I now believe that checked exceptions encourage people to make them vanish. Plus they make much less readable code.

In the end, I think we must realize the experimental nature of exceptions and look at them carefully before assuming that everything about exceptions in Java are good. I believe that having a single mechanism for handling errors is excellent, and I believe that using a separate channel (the exception handling mechanism) for moving the exceptions around is good. But I do remember one of the early arguments for exception handling in C++ was that it would allow the programmer to separate the sections of code where you just wanted to get work done from the sections where you handled errors, and it seems to me that checked exceptions do not do this; instead, they tend to intrude (a lot) into your "normal working code" and thus are a step backwards. My experience with Python exceptions supports this, and unless I get turned around on this issue I intend to put a lot more RuntimeExceptions into my Java code.

#[BT_4]#


The pattern concept

“Design patterns help you learn from others' successes instead of your own failures[2].”

#[BT_6]#Probably the most important step forward in object-oriented design is the “design patterns” movement, chronicled in Design Patterns (ibid)[3]. That book shows 23 different solutions to particular classes of problems. In this book, the basic concepts of design patterns will be introduced along with examples. This should whet your appetite to read Design Patterns by Gamma, et. al., a source of what has now become an essential, almost mandatory, vocabulary for OOP programmers.

#[BT_7]#The latter part of this book contains an example of the design evolution process, starting with an initial solution and moving through the logic and process of evolving the solution to more appropriate designs. The program shown (a trash sorting simulation) has evolved over time, and you can look at that evolution as a prototype for the way your own design can start as an adequate solution to a particular problem and evolve into a flexible approach to a class of problems.

What is a pattern?

#[BT_8]#Initially, you can think of a pattern as an especially clever and insightful way of solving a particular class of problems. That is, it looks like a lot of people have worked out all the angles of a problem and have come up with the most general, flexible solution for it. The problem could be one you have seen and solved before, but your solution probably didn’t have the kind of completeness you’ll see embodied in a pattern.

#[BT_9]#Although they’re called “design patterns,” they really aren’t tied to the realm of design. A pattern seems to stand apart from the traditional way of thinking about analysis, design, and implementation. Instead, a pattern embodies a complete idea within a program, and thus it can sometimes appear at the analysis phase or high-level design phase. This is interesting because a pattern has a direct implementation in code and so you might not expect it to show up before low-level design or implementation (and in fact you might not realize that you need a particular pattern until you get to those phases).

#[BT_10]#The basic concept of a pattern can also be seen as the basic concept of program design: adding a layer of abstraction. Whenever you abstract something you’re isolating particular details, and one of the most compelling motivations behind this is to separate things that change from things that stay the same. Another way to put this is that once you find some part of your program that’s likely to change for one reason or another, you’ll want to keep those changes from propagating other changes throughout your code. Not only does this make the code much cheaper to maintain, but it also turns out that it is usually simpler to understand (which results in lowered costs).

#[BT_11]#Often, the most difficult part of developing an elegant and cheap-to-maintain design is in discovering what I call “the vector of change.” (Here, “vector” refers to the maximum gradient and not a container class.) This means finding the most important thing that changes in your system, or put another way, discovering where your greatest cost is. Once you discover the vector of change, you have the focal point around which to structure your design.

#[BT_12]#So the goal of design patterns is to isolate changes in your code. If you look at it this way, you’ve been seeing some design patterns already in this book. For example, inheritance can be thought of as a design pattern (albeit one implemented by the compiler). It allows you to express differences in behavior (that’s the thing that changes) in objects that all have the same interface (that’s what stays the same). Composition can also be considered a pattern, since it allows you to change—dynamically or statically—the objects that implement your class, and thus the way that class works.

#[BT_13]#You’ve also already seen another pattern that appears in Design Patterns: the iterator (Java 1.0 and 1.1 capriciously calls it the Enumeration; Java 2 containers use “iterator”). This hides the particular implementation of the container as you’re stepping through and selecting the elements one by one. The iterator allows you to write generic code that performs an operation on all of the elements in a sequence without regard to the way that sequence is built. Thus your generic code can be used with any container that can produce an iterator.

Pattern taxonomy

#[BT_14]#One of the events that’s occurred with the rise of design patterns is what could be thought of as the “pollution” of the term – people have begun to use the term to mean just about anything synonymous with “good.” After some pondering, I’ve come up with a sort of hierarchy describing a succession of different types of categories:

1.      #[BT_15]#Idiom: how we write code in a particular language to do this particular type of thing. This could be something as common as the way that you code the process of stepping through an array in C (and not running off the end).

2.     #[BT_16]#Specific Design: the solution that we came up with to solve this particular problem. This might be a clever design, but it makes no attempt to be general.

3.     #[BT_17]#Standard Design: a way to solve this kind of problem. A design that has become more general, typically through reuse.

4.     #[BT_18]#Design Pattern: how to solve an entire class of similar problem. This usually only appears after applying a standard design a number of times, and then seeing a common pattern throughout these applications.

#[BT_19]#I feel this helps put things in perspective, and to show where something might fit. However, it doesn’t say that one is better than another. It doesn’t make sense to try to take every problem solution and generalize it to a design pattern – it’s not a good use of your time, and you can’t force the discovery of patterns that way; they tend to be subtle and appear over time.

#[BT_20]#One could also argue for the inclusion of Analysis Pattern and Architectural Pattern in this taxonomy.

Design principles

(Update from slides to here)

When I put out a call for ideas in my newsletter[4], a number of suggestions came back which turned out to be very useful, but different than the above classification, and I realized that a list of design principles is at least as important as design structures, but for a different reason: these allow you to ask questions about your proposed design, to apply tests for quality.

·         Principle of least astonishment (don’t be astonishing).

·         Make common things easy, and rare things possible

·         Consistency. One thing has become very clear to me, especially because of Python: the more random rules you pile onto the programmer, rules that have nothing to do with solving the problem at hand, the slower the programmer can produce. And this does not appear to be a linear factor, but an exponential one.

·         Law of Demeter: a.k.a. “Don’t talk to strangers.” An object should only reference itself, its attributes, and the arguments of its methods.

·         Subtraction: a design is finished when you cannot take anything else away.

·         Simplicity before generality[5]. (A variation of Occam’s Razor, which says “the simplest solution is the best”). A common problem we find in frameworks is that they are designed to be general purpose without reference to actual systems. This leads to a dizzying array of options that are often unused, misused or just not useful. However, most developers work on specific systems, and the quest for generality does not always serve them well. The best route to generality is through understanding well-defined specific examples. So, this principle acts as the tie breaker between otherwise equally viable design alternatives. Of course, it is entirely possible that the simpler solution is the more general one.

·         Reflexivity (my suggested term). One abstraction per class, one class per abstraction. Might also be called Isomorphism.

·         Independence or Orthogonality. Express independent ideas independently. This complements Separation, Encapsulation and Variation, and is part of the Low-Coupling-High-Cohesion message.

·         Once and once only: Avoid duplication of logic and structure where the duplication is not accidental, ie where both pieces of code express the same intent for the same reason.

In the process of brainstorming this idea, I hope to come up with a small handful of fundamental ideas that can be held in your head while you analyze a problem. However, other ideas that come from this list may end up being useful as a checklist while walking through and analyzing your design.

Classifying patterns

#[BT_27]#The Design Patterns book discusses 23 different patterns, classified under three purposes (all of which revolve around the particular aspect that can vary). The three purposes are:

1.              Creational: how an object can be created. This often involves isolating the details of object creation so your code isn’t dependent on what types of objects there are and thus doesn’t have to be changed when you add a new type of object. The aforementioned Singleton is classified as a creational pattern, and later in this book you’ll see examples of Factory Method and Prototype.

2.              Structural: designing objects to satisfy particular project constraints. These work with the way objects are connected with other objects to ensure that changes in the system don’t require changes to those connections.

3.              Behavioral: objects that handle particular types of actions within a program. These encapsulate processes that you want to perform, such as interpreting a language, fulfilling a request, moving through a sequence (as in an iterator), or implementing an algorithm. This book contains examples of the Observer and the Visitor patterns.

#[BT_28]#The Design Patterns book has a section on each of its 23 patterns along with one or more examples for each, typically in C++ (rather restricted C++, at that) but sometimes in Smalltalk. (You’ll find that this doesn’t matter too much since you can easily translate the concepts from either language into Java.) This book will revisit many of the patterns shown in Design Patterns but with a Java orientation, since the language changes the expression and understanding of the patterns. However, the GoF examples will not be repeated here, since I believe that it’s possible to produce more illuminating examples given some effort. The goal is to provide you with a decent feel for what patterns are about and why they are so important.

#[BT_29]#After years of looking at these things, it began to occur to me that the patterns themselves use basic principles of organization, other than (and more fundamental than) those described in Design Patterns. These principles are based on the structure of the implementations, which is where I have seen great similarities between patterns (more than those expressed in Design Patterns). Although we generally try to avoid implementation in favor of interface, for awhile I thought that it was easier to understand the patterns in terms of these structural principles, and tried reorganizing the book around the patterns based on their structure instead of the categories presented in Design Patterns.

However, a later insight made me realize that it’s more useful to organize the patterns in terms of the problems they solve. I believe this is a subtle but important distinction from the way Metsker organizes the patterns by intent in Design Patterns Java Workshop (Addison-Wesley 2002), because I hope that you will then be able to recognize your problem and search for a solution, if the patterns are organized this way.

In the process of doing all this “book refactoring” I realized that if I changed it once, I would probably change it again (there’s definitely a design maxim in there), so I removed all references to chapter numbers in order to facilitate this change (the little-known “numberless chapter” pattern J).HowHH

The development challenge

#[BT_30]#Issues of development, the UML process, Extreme Programming.

#[BT_31]#Is evaluation valuable? The Capability Immaturity Model:

#[BT_32]#Wiki Page: http://c2.com/cgi-bin/wiki?CapabilityImMaturityModel
Article: http://www.embedded.com/98/9807br.htm

#[BT_33]#Pair programming research:

#[BT_34]#http://collaboration.csc.ncsu.edu/laurie/

Unit testing

In an earlier version of this book I decided that unit testing was essential (for all of my books) and that JUnit was too verbose and clunky to consider. At that time I wrote my own unit testing framework using Java reflection to simplify the syntax necessary to achieve unit testing. For the third edition of Thinking in Java, we developed another unit testing framework for that book which would test the output of examples.

In the meantime, JUnit has changed to add a syntax remarkably similar to the one that I used in an earlier version of this book. I don’t know how much influence I may have had on that change, but I’m simply happy that it has happened, because I no longer feel the need to support my own system (which you can still find <some URL here>) and can simply recommend the defacto standard.

I have introduced and described the style of JUnit coding that I consider a “best practice” (primarily because of simplicity), in Thinking in Java, 3rd edition, chapter 15. That section provides an adequate introduction to any of the unit testing you will see associated with this book (however, the unit testing code will not normally be included in the text of this book). When you download the code for this book, you will find (4/9/2003: Eventually, not yet) unit tests along with the code examples whenever possible.

Location of test code

(From Bill):

Public: in test subdirectory; different package (don’t include in jar).

Package access: same package, subdirectory path underneath library code (don’t include in jar)

Private access: (white box testing). Nested class, strip out, or Junit addons.

Simplifying Idioms

Before getting into more complex techniques, it’s helpful to look at some basic ways to keep code simple and straightforward.

Messenger

The most trivial of these is the messenger, which simply packages information into an object to be passed around, instead of passing all the pieces around separately. Note that without the messenger, the code for translate() would be much more confusing to read:

//: simplifying:MessengerDemo.java

package simplifying;

import junit.framework.*;

 

class Point { // A messenger

  public int x, y, z; // Since it's just a carrier

  public Point(int x, int y, int z) {

    this.x = x;

    this.y = y;

    this.z = z;

  }

  public Point(Point p) { // Copy-constructor

    this.x = p.x;

    this.y = p.y;

    this.z = p.z;

  }

  public String toString() {

    return "x: " + x + " y: " + y + " z: " + z;

  }

}

 

class Vector {

  public int magnitude, direction;

  public Vector(int magnitude, int direction) {

    this.magnitude = magnitude;

    this.direction = direction;

  }

}

 

class Space {

  public static Point translate(Point p, Vector v) {

    p = new Point(p); // Don't modify the original

    // Perform calculation using v. Dummy calculation:

    p.x = p.x + 1;

    p.y = p.y + 1;

    p.z = p.z + 1;

    return p;

  }

}

 

public class MessengerDemo extends TestCase {

  public void test() {

    Point p1 = new Point(1, 2, 3);

    Point p2 = Space.translate(p1, new Vector(11, 47));

    String result = "p1: " + p1 + " p2: " + p2;

    System.out.println(result);

    assertEquals(result,

      "p1: x: 1 y: 2 z: 3 p2: x: 2 y: 3 z: 4");

  }  

  public static void main(String[] args) {

    junit.textui.TestRunner.run(MessengerDemo.class);

  }

} ///:~

 

Since the goal of a messenger is only to carry data, that data is made public for easy access. However, you may also have reasons to make the fields private.

Collecting Parameter

Messenger’s big brother is the collecting parameter, whose job is to capture information from the method to which it is passed. Generally, this is used when the collecting parameter is passed to multiple methods, so it’s like a bee collecting pollen.

A container makes an especially useful collecting parameter, since it is already set up to dynamically add objects:

//: simplifying:CollectingParameterDemo.java

package simplifying;

import java.util.*;

import junit.framework.*;

 

class CollectingParameter extends ArrayList {}

 

class Filler {

  public void f(CollectingParameter cp) {

    cp.add("accumulating");

  }

  public void g(CollectingParameter cp) {

    cp.add("items");

  }

  public void h(CollectingParameter cp) {

    cp.add("as we go");

  }

}

 

public class CollectingParameterDemo extends TestCase {

  public void test() {

    Filler filler = new Filler();

    CollectingParameter cp = new CollectingParameter();

    filler.f(cp);

    filler.g(cp);

    filler.h(cp);

    String result = "" + cp;

    System.out.println(cp);

    assertEquals(result,"[accumulating, items, as we go]");

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(

      CollectingParameterDemo.class);

  }

} ///:~

 

The collecting parameter must have some way to set or insert values. Note that by this definition, a messenger could be used as a collecting parameter. The key is that a collecting parameter is passed about and modified by the methods it is passed to.

Object quantity

The two patterns described here are solely used to control the quantity of objects.

Singleton could actually be thought of as a special case of Object Pool, but the applications of the Object Pool tend to be uniqe enough from Singleton that it’s worth treating the two separately.

Singleton

#[BT_21]#Possibly the simplest design pattern is the singleton, which is a way to provide one and only one object of a particular type.  An important aspect of Singleton is that you provide a global access point, so singletons are often a solution for what you would have used a global variable for in C. In addition, a singleton often has the characteristics of a registry or lookup service – it’s a place you go to find references to other objects.

Singletons can be found in the Java libraries, but here’s a more direct example:

//: singleton:SingletonPattern.java

// The Singleton design pattern: you can

// never instantiate more than one.

package singleton;

import junit.framework.*;

 

// Since this isn't inherited from a Cloneable

// base class and cloneability isn't added,

// making it final prevents cloneability from

// being added through inheritance:

 

final class Singleton {

  private static Singleton s = new Singleton(47);

  private int i;

  private Singleton(int x) { i = x; }

  public static Singleton getReference() {

    return s;

  }

  public int getValue() { return i; }

  public void setValue(int x) { i = x; }

}

 

public class SingletonPattern extends TestCase {

  public void test() {

    Singleton s = Singleton.getReference();

    String result = "" + s.getValue();

    System.out.println(result);

    assertEquals(result, "47");

    Singleton s2 = Singleton.getReference();

    s2.setValue(9);

    result = "" + s.getValue();

    System.out.println(result);

    assertEquals(result, "9");

    try {

      // Can't do this: compile-time error.

      // Singleton s3 = (Singleton)s2.clone();

    } catch(Exception e) {

      throw new RuntimeException(e);

    }

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(SingletonPattern.class);

  }

} ///:~

 

#[BT_22]#

#[BT_23]#The key to creating a singleton is to prevent the client programmer from having any way to create an object except the ways you provide. You must make all constructors private, and you must create at least one constructor to prevent the compiler from synthesizing a default constructor for you (which it will create using package access).

#[BT_24]#At this point, you decide how you’re going to create your object. Here, it’s created statically, but you can also wait until the client programmer asks for one and create it on demand. In any case, the object should be stored privately. You provide access through public methods. Here, getReference( ) produces the reference to the Singleton object. The rest of the interface (getValue( ) and setValue( )) is the regular class interface.

#[BT_25]#Java also allows the creation of objects through cloning. In this example, making the class final prevents cloning. Since Singleton is inherited directly from Object, the clone( ) method remains protected so it cannot be used (doing so produces a compile-time error). However, if you’re inheriting from a class hierarchy that has already overridden clone( ) as public and implemented Cloneable, the way to prevent cloning is to override clone( ) and throw a CloneNotSupportedException as described in Appendix A of Thinking in Java, 2nd edition. (You could also override clone( ) and simply return this, but that would be deceiving since the client programmer would think they were cloning the object, but would instead still be dealing with the original.) Actually, this isn’t precisely true, because even in the above situation someone could still use reflection to invoke clone( ) [[is this true? clone( ) is still protected so I’m not so sure. If it is true, you’d have to throw CloneNotSupportedException as the only way to guarantee un-cloneability ]]

Exercises

             1.             SingletonPattern.java always creates an object, even if it’s never used. Modify this program to use lazy initialization, so the singleton object is only created the first time that it is needed.

             2.             Create a registry/lookup service that accepts a Java interface and produces a reference to an object that implements that interface.

Object pool

#[BT_26]#Note that you aren’t restricted to creating only one object. This is also a technique to create a limited pool of objects. In that situation, however, you can be confronted with the problem of sharing objects in the pool. If this is an issue, you can create a solution involving a check-out and check-in of the shared objects.AsAAAAA

As an example, consider a database. Commercial databases often restrict the number of connections that you can use at any one time. Here is an implementation that uses an object pool to manage the connections. First, the basic concept of managing a pool of objects is implemented as a separate class:

//: singleton:PoolManager.java

package singleton;

import java.util.*;

 

public class PoolManager {

  private static class PoolItem {

    boolean inUse = false;

    Object item;

    PoolItem(Object item) { this.item = item; }

  }

  private ArrayList items = new ArrayList();

  public void add(Object item) {

    items.add(new PoolItem(item));

  }

  static class EmptyPoolException extends Exception {}

  public Object get() throws EmptyPoolException {

    for(int i = 0; i < items.size(); i++) {

      PoolItem pitem = (PoolItem)items.get(i);

      if(pitem.inUse == false) {

        pitem.inUse = true;

        return pitem.item;

      }

    }

    // Fail early:

    throw new EmptyPoolException();

    // return null; // Delayed failure

  }

  public void release(Object item) {

    for(int i = 0; i < items.size(); i++) {

      PoolItem pitem = (PoolItem)items.get(i);

      if(item == pitem.item) {

        pitem.inUse = false;

        return;

      }

    }

    throw new RuntimeException(item + " not found");

  }

} ///:~

 

 

 

//: singleton:ConnectionPoolDemo.java

package singleton;

import junit.framework.*;

 

interface Connection {

  Object get();

  void set(Object x);

}

 

class ConnectionImplementation implements Connection {

  public Object get() { return null; }

  public void set(Object s) {}

}

 

class ConnectionPool { // A singleton

  private static PoolManager pool = new PoolManager();

  public static void addConnections(int number) {

    for(int i = 0; i < number; i++)

      pool.add(new ConnectionImplementation());

  }

  public static Connection getConnection()

  throws PoolManager.EmptyPoolException {

    return (Connection)pool.get();

  }

  public static void releaseConnection(Connection c) {

    pool.release(c);

  }

}

 

public class ConnectionPoolDemo extends TestCase  {

  static {

    ConnectionPool.addConnections(5);

  }

  public void test() {

    Connection c = null;

    try {

      c = ConnectionPool.getConnection();

    } catch (PoolManager.EmptyPoolException e) {

      throw new RuntimeException(e);

    }

    c.set(new Object());

    c.get();

    ConnectionPool.releaseConnection(c);

  }

  public void test2() {

    Connection c = null;

    try {

      c = ConnectionPool.getConnection();

    } catch (PoolManager.EmptyPoolException e) {

      throw new RuntimeException(e);

    }

    c.set(new Object());

    c.get();

    ConnectionPool.releaseConnection(c);

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(ConnectionPoolDemo.class);

  }

} ///:~

 

 

 

Exercises

             1.             Add unit tests to ConnectionPoolDemo.java to demonstrate the problem that the client may release the connection but still continue to use it.

#[BT_35]#

#[BT_36]#


Object decoupling

#[BT_92]#Both Proxy and State provide a surrogate class that you use in your code; the real class that does the work is hidden behind this surrogate class. When you call a method in the surrogate, it simply turns around and calls the method in the implementing class. These two patterns are so similar that the Proxy is simply a special case of State. One is tempted to just lump the two together into a pattern called Surrogate, but the term “proxy” has a long-standing and specialized meaning, which probably explains the reason for the two different patterns.

#[BT_93]#The basic idea is simple: from a base class, the surrogate is derived along with the class or classes that provide the actual implementation:

#[BT_94]#

#[BT_95]#When a surrogate object is created, it is given an implementation to which to send all of the method calls.

#[BT_96]#Structurally, the difference between Proxy and State is simple: a Proxy has only one implementation, while State has more than one. The application of the patterns is considered (in Design Patterns) to be distinct: Proxy is used to control access to its implementation, while State allows you to change the implementation dynamically. However, if you expand your notion of “controlling access to implementation” then the two fit neatly together.

Proxy: fronting for another object

#[BT_97]#If we implement Proxy by following the above diagram, it looks like this:

//: proxy:ProxyDemo.java

// Simple demonstration of the Proxy pattern.

package proxy;

import junit.framework.*;

 

interface ProxyBase {

  void f();

  void g();

  void h();

}

 

class Proxy implements ProxyBase {

  private ProxyBase implementation;

  public Proxy() {

    implementation = new Implementation();

  }

  // Pass method calls to the implementation:

  public void f() { implementation.f(); }

  public void g() { implementation.g(); }

  public void h() { implementation.h(); }

}

 

class Implementation implements ProxyBase {

  public void f() {

    System.out.println("Implementation.f()");

  }

  public void g() {

    System.out.println("Implementation.g()");

  }

  public void h() {

    System.out.println("Implementation.h()");

  }

}

 

public class ProxyDemo extends TestCase  {

  Proxy p = new Proxy();

  public void test() {

    // This just makes sure it will complete

    // without throwing an exception.

    p.f();

    p.g();

    p.h();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(ProxyDemo.class);

  }

} ///:~

#[BT_98]#

#[BT_99]#Of course, it isn’t necessary that Implementation have the same interface as Proxy; as long as Proxy is somehow “speaking for” the class that it is referring method calls to then the basic idea is satisfied (note that this statement is at odds with the definition for Proxy in GoF). However, it is convenient to have a common interface so that Implementation is forced to fulfill all the methods that Proxy needs to call.

The PoolManager using Proxy

//: proxy:PoolManager.java

package proxy;

import java.util.*;

 

public class PoolManager {

  private static class PoolItem {

    boolean inUse = false;

    Object item;

    PoolItem(Object item) { this.item = item; }

  }

  public class ReleasableReference {  // Used to build the proxy

    private PoolItem reference;

    private boolean released = false;

    public ReleasableReference(PoolItem reference) {

      this.reference = reference;

    }

    public Object getReference() {

      if(released)

        throw new RuntimeException(

          "Tried to use reference after it was released");

      return reference.item;

    }

    public void release() {

      released = true;

      reference.inUse = false;

    }

  }

  private ArrayList items = new ArrayList();

  public void add(Object item) {

    items.add(new PoolItem(item));

  }

  // Different (better?) approach to running out of items:

  public static class EmptyPoolItem {}

  public ReleasableReference get() {

    for(int i = 0; i < items.size(); i++) {

      PoolItem pitem = (PoolItem)items.get(i);

      if(pitem.inUse == false) {

        pitem.inUse = true;

        return new ReleasableReference(pitem);

      }

    }

    // Fail as soon as you try to cast it:

    // return new EmptyPoolItem();

    return null; // temporary

  }

} ///:~

 

 

//: proxy:ConnectionPoolProxyDemo.java

package proxy;

import junit.framework.*;

 

interface Connection {

  Object get();

  void set(Object x);

  void release();

}

 

class ConnectionImplementation implements Connection {

  public Object get() { return null; }

  public void set(Object s) {}

  public void release() {} // Never called directly

}

 

class ConnectionPool { // A singleton

  private static PoolManager pool = new PoolManager();

  private ConnectionPool() {} // Prevent synthesized constructor

  public static void addConnections(int number) {

    for(int i = 0; i < number; i++)

      pool.add(new ConnectionImplementation());

  }

  public static Connection getConnection() {

    PoolManager.ReleasableReference rr =

      (PoolManager.ReleasableReference)pool.get();

    if(rr == null) return null;

    return new ConnectionProxy(rr);

  }

  // The proxy as a nested class:

  private static

  class ConnectionProxy implements Connection {

    private PoolManager.ReleasableReference implementation;

    public

    ConnectionProxy(PoolManager.ReleasableReference rr) {

      implementation = rr;

    }

    public Object get() {

      return

        ((Connection)implementation.getReference()).get();

    }

    public void set(Object x) {

      ((Connection)implementation.getReference()).set(x);

    }

    public void release() { implementation.release(); }

  }

}

 

public class ConnectionPoolProxyDemo extends TestCase {

  static {

    ConnectionPool.addConnections(5);

  }

  public void test() {

    Connection c = ConnectionPool.getConnection();

    c.set(new Object());

    c.get();

    c.release();

  }

  public void testDisable() {

    Connection c = ConnectionPool.getConnection();

    String s = null;

    c.set(new Object());

    c.get();

    c.release();

    try {

      c.get();

    } catch(Exception e) {

      s = e.getMessage();

      System.out.println(s);

    }

    assertEquals(s,

      "Tried to use reference after it was released");

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(

      ConnectionPoolProxyDemo.class);

  }

} ///:~

 

 

 

Dynamic Proxies

In JDK 1.3, the Dynamic Proxy was introduced. Although a little complex at first, this is an intruiging tool.

Here's an interesting little starting example, which works and proves that yes, indeed, the invocation handler is being called so the proxying etc. is actually working. So it's pretty cool, and it's in my head now, but I still have to figure out something reasonable to do with the invocation handler to come up with a useful example...

// proxy:DynamicProxyDemo.java

// Broken in JDK 1.4.1_01

package proxy;

import java.lang.reflect.*;

 

interface Foo {

  void f(String s);

  void g(int i);

  String h(int i, String s);

}

 

public class DynamicProxyDemo {

  public static void main(String[] clargs) {

    Foo prox = (Foo)Proxy.newProxyInstance(

       Foo.class.getClassLoader(),

       new Class[]{ Foo.class },

       new InvocationHandler() {

        public Object invoke(

          Object proxy, Method method,

          Object[] args) {

            System.out.println(

              "InvocationHandler called:" +

              "\n\tMethod = " + method);

            if (args != null) {

              System.out.println("\targs = ");

              for (int i = 0; i < args.length; i++)

                System.out.println("\t\t" + args[i]);

            }

          return null;

        }

      });

    prox.f("hello");

    prox.g(47);

    prox.h(47, "hello");

  }

} ///:~

 

Exercise: Use the Java dynamic proxy to create an object that acts as a front end for a simple configuration file. For example, in good_stuff.txt you can have entries like this:

a=1

b=2

c="Hello World"

 

A client programmer of this NeatPropertyBundle could then write:

NeatPropertyBundle p =

  new NeatPropertyBundle("good_stuff");

System.out.println(p.a);

System.out.println(p.b);

System.out.println(p.c);

 

The contents of the configuration file can contain anything, with any variable names. The dynamic proxy will either map to the name or tell you it doesn’t exist somehow (probably by returning null). If you set a property and it doesn’t already exist, the dynamic proxy will create the new entry. The toString( ) method should display all the current entries.

Exercise: similar to the previous exercise, use the Java dynamic proxy to make a connection to the DOS Autoexec.bat file.

Exercise: Accept an SQL query which returns data, then read the DB metadata.  Now, for each record, provide an object which has attributes corresponding to the column names and of appropriate data types. 

Exercise: Create a simple server and client that uses XML-RPC. Each object the client returns should use the dynamic proxy concept to exercise the remote methods.

Andrea writes:

I'm not sure about the exercises you suggest, except for the last one. The thing is that I like to think at invocation handler as somthing providing features that are orthogonal to the ones provided by the object being "proxied".

In other words: the implementation of the invocation handler is completely independent from the interface(s) of the object that the dynamically-generated proxy represent. Which means that once you have implemented an invocation handler, you can use for any class that exposes interfaces, even for classes and interfaces that were not present when the handler was implemented.

That's why I say the the handler provides services that are orthogonal to the ones provided by the proxied object. Rickard has a few handlers in his SmartWorld example, and they one I like the best is a call-retry handler. It basically makes a call into the actual object, and if the call generates an exception if waits for a while, then makes the same call again for a total of three times. If all three calls fails, it returns an exception. And you can use such a handler on _any_ class.

The implementation is way too complex for what you are trying to demonstrate. I'm using this example just to explain what I mean by orthogonal services.

In your list of exercises, the only one that, in my opinion, makes sense to implement using dynamic proxies is the last one, the one using XML-RPC to communicate with an object. And that's because the mechanism you use to dispatch the message (XML-RPC) is orthogonal to the services provided by the object you want to reach.

State: changing object behavior

An object that appears to change its class.

Indications: conditional code in most or all methods.

#[BT_100]#The State pattern switches from one implementation to another during the lifetime of the surrogate, in order to produce different behavior from the same method call(s). It’s a way to improve the implementation of your code when you seem to be doing a lot of testing inside each of your methods before deciding what to do for that method. For example, the fairy tale of the frog-prince contains an object (the creature) that behaves differently depending on what state it’s in. You could implement this using a boolean that you test:

//: state:KissingPrincess.java

package state;

import junit.framework.*;

 

class Creature {

  private boolean isFrog = true;

  public void greet() {

    if(isFrog)

      System.out.println("Ribbet!");

    else

      System.out.println("Darling!");

  }

  public void kiss() { isFrog = false; }

}

 

public class KissingPrincess extends TestCase  {

  Creature creature = new Creature();

  public void test() {

    creature.greet();

    creature.kiss();

    creature.greet();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(KissingPrincess.class);

  }

} ///:~

 

However, the greet() method, and any other methods that must test isFrog before they perform their operations, ends up with awkward code. By delegating the operations to a State object that can be changed, this code is simplified.

//: state:KissingPrincess2.java

package state;

import junit.framework.*;

 

class Creature {

  private interface State {

    String response();

  }

  private class Frog implements State {

    public String response() { return "Ribbet!"; }

  }

  private class Prince implements State {

    public String response() { return "Darling!"; }

  }

  private State state = new Frog();

  public void greet() {

    System.out.println(state.response());

  }

  public void kiss() { state = new Prince(); }

}

 

public class KissingPrincess2 extends TestCase  {

  Creature creature = new Creature();

  public void test() {

    creature.greet();

    creature.kiss();

    creature.greet();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(KissingPrincess2.class);

  }

} ///:~

 

In addition, changes to the State are automatically propagated throughout, rather than requiring an edit across the class methods in order to effect changes.

Here’s the basic structure of State:[[ [[

//: state:StateDemo.java

// Simple demonstration of the State pattern.

package state;

import junit.framework.*;

 

interface State {

  void operation1();

  void operation2();

  void operation3();

}

 

class ServiceProvider {

  private State state;

  public ServiceProvider(State state) {

    this.state = state;

  }

  public void changeState(State newState) {

    state = newState;

  }

  // Pass method calls to the implementation:

  public void service1() {

    // ...

    state.operation1();

    // ...

    state.operation3();

  }

  public void service2() {

    // ...

    state.operation1();

    // ...

    state.operation2();

  }

  public void service3() {

    // ...

    state.operation3();

    // ...

    state.operation2();

  }

}

 

class Implementation1 implements State {

  public void operation1() {

    System.out.println("Implementation1.operation1()");

  }

  public void operation2() {

    System.out.println("Implementation1.operation2()");

  }

  public void operation3() {

    System.out.println("Implementation1.operation3()");

  }

}

 

class Implementation2 implements State {

  public void operation1() {

    System.out.println("Implementation2.operation1()");

  }

  public void operation2() {

    System.out.println("Implementation2.operation2()");

  }

  public void operation3() {

    System.out.println("Implementation2.operation3()");

  }

}

 

public class StateDemo extends TestCase  {

  static void run(ServiceProvider sp) {

    sp.service1();

    sp.service2();

    sp.service3();

  }

  ServiceProvider sp =

    new ServiceProvider(new Implementation1());

  public void test() {

    run(sp);

    sp.changeState(new Implementation2());

    run(sp);

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(StateDemo.class);

  }

} ///:~

 

 

#[BT_101]#

#[BT_102]#In main( ), you can see that the first implementation is used for a bit, then the second implementation is swapped in and that is used.

There are a number of details that are choices that you must make according to the needs of your own implementation, such as whether the fact that you are using State is exposed to the client, and how the changes to State are made. Sometimes (as in the Swing LayoutManager) the client may pass in the object directly, but in KissingPrincess2.java the fact that State is used is invisible to the client. In addition, the mechanism for changing state may be simple or complex – in State Machine, described later in this book, larger sets of states and different mechanisms for changing are explored.

The Swing LayoutManager example mentioned above is an interesting example because it show behavior of both Strategy and State.

#[BT_103]#The difference between Proxy and State is in the problems that are solved. The common uses for Proxy as described in Design Patterns are:

1.              Remote proxy. This proxies for an object in a different address space. A remote proxy is created for you automatically by the RMI compiler rmic as it creates stubs and skeletons.

2.              Virtual proxy. This provides “lazy initialization” to create expensive objects on demand.

3.              Protection proxy. Used when you don’t want the client programmer to have full access to the proxied object.

4.              Smart reference. To add additional actions when the proxied object is accessed. For example, or to keep track of the number of references that are held for a particular object, in order to implement the copy-on-write idiom and prevent object aliasing. A simpler example is keeping track of the number of calls to a particular method.

#[BT_104]#You could look at a Java reference as a kind of protection proxy, since it controls access to the actual object on the heap (and ensures, for example, that you don’t use a null reference).

#[BT_105]#[[ Rewrite this: In Design Patterns, Proxy and State are not seen as related to each other because the two are given (what I consider arbitrarily) different structures. State, in particular, uses a separate implementation hierarchy but this seems to me to be unnecessary unless you have decided that the implementation is not under your control (certainly a possibility, but if you own all the code there seems to be no reason not to benefit from the elegance and helpfulness of the single base class). In addition, Proxy need not use the same base class for its implementation, as long as the proxy object is controlling access to the object it “fronting” for. Regardless of the specifics, in both Proxy and State a surrogate is passing method calls through to an implementation object.]]]

State can be found everywhere because it’s such a fundamental idea. For example, in Builder, the “Director” uses a backend Builder object to produce different behaviors.Stat

Iterators: decoupling algorithms from containers

Alexander Stepanov thought for years about the problem of generic programming techniques before creating the STL (along with Dave Musser). He came to the conclusion that all algorithms are defined on algebraic structures – what we would call containers.

#[BT_193]#In the process, he realized that iterators are central to the use of algorithms, because they decouple the algorithms from the specific type of container that the algorithm might currently be working with. This means that you can describe the algorithm without worrying about the particular sequence it is operating on. More generally, any code that you write using iterators is decoupled from the data structure that the code is manipulating, and thus your code is more general and reusable.

#[BT_194]#The use of iterators also extends your code into the realm of functional programming, whose objective is to describe what a program is doing at every step rather than how it is doing it. That is, you say “sort” rather than describing the sort. The objective of the C++ STL was to provide this generic programming approach for C++ (how successful this approach will actually be remains to be seen).

#[BT_195]#If you’ve used containers in Java (and it’s hard to write code without using them), you’ve used iterators – in the form of the Enumeration in Java 1.0/1.1 and the Iterator in Java 2. So you should already be familiar with their general use. If not, see Chapter 9, Holding Your Objects, under Iterators in Thinking in Java, 2nd edition (freely downloadable from www.BruceEckel.com).

#[BT_196]#Because the Java 2 containers rely heavily on iterators they become excellent candidates for generic/functional programming techniques. This chapter will explore these techniques by converting the STL algorithms to Java, for use with the Java 2 container library.

Type-safe iterators

#[BT_197]#In Thinking in Java, 2nd edition, I show the creation of a type-safe container that will only accept a particular type of object. A reader, Linda Pazzaglia, asked for the other obvious type-safe component, an iterator that would work with the basic java.util containers, but impose the constraint that the type of objects that it iterates over be of a particular type.

#[BT_198]#If Java ever includes a template mechanism, this kind of iterator will have the added advantage of being able to return a specific type of object, but without templates you are forced to return generic Objects, or to require a bit of hand-coding for every type that you want to iterate through. I will take the former approach.

#[BT_199]#A second design decision involves the time that the type of object is determined. One approach is to take the type of the first object that the iterator encounters, but this is problematic because the containers may rearrange the objects according to an internal ordering mechanism (such as a hash table) and thus you may get different results from one iteration to the next. The safe approach is to require the user to establish the type during construction of the iterator.

#[BT_200]#Lastly, how do we build the iterator? We cannot rewrite the existing Java library classes that already produce Enumerations and Iterators. However, we can use the Decorator design pattern, and create a class that simply wraps the Enumeration or Iterator that is produced, generating a new object that has the iteration behavior that we want (which is, in this case, to throw a RuntimeException if an incorrect type is encountered) but with the same interface as the original Enumeration or Iterator, so that it can be used in the same places (you may argue that this is actually a Proxy pattern, but it’s more likely Decorator because of its intent). Here is the code:

//: com:bruceeckel:util:TypedIterator.java

package com.bruceeckel.util;

import java.util.*;

 

public class TypedIterator implements Iterator {

  private Iterator imp;

  private Class type;

  public TypedIterator(Iterator it, Class type) {

    imp = it;

    this.type = type;

  }

  public boolean hasNext() {

    return imp.hasNext();

  }

  public void remove() { imp.remove(); }

  public Object next() {

    Object obj = imp.next();

    if(!type.isInstance(obj))

      throw new ClassCastException(

        "TypedIterator for type " + type +

        " encountered type: " + obj.getClass());

    return obj;

  }

} ///:~

 

Exercises

             1.             Create an example of the “virtual proxy.”

             2.             Create an example of the “Smart reference” proxy where you keep count of the number of method calls to a particular object.

             3.             Create a program similar to certain DBMS systems that only allow a certain number of connections at any time. To implement this, use a singleton-like system that controls the number of “connection” objects that it creates. When a user is finished with a connection, the system must be informed so that it can check that connection back in to be reused. To guarantee this, provide a proxy object instead of a reference to the actual connection, and design the proxy so that it will cause the connection to be released back to the system.

             4.             Using the State pattern, make a class called UnpredictablePerson which changes the kind of response to its hello( ) method depending on what kind of Mood it’s in. Add an additional kind of Mood called Prozac.

             5.             Create a simple copy-on write implementation.

             6.             The java.util.Map has no way to automatically load a two-dimensional array of objects into a Map as key-value pairs. Create an adapter class that does this.

             7.             Create an Adapter Factory that dynamically finds and produces the adapter that you need to connect a given object to a desired interface.

             8.             Solve the above exercise using the dynamic proxy that’s part of the Java standard library.

             9.             Modify the Object Pool solution so that the objects are returned to the pool automatically after a certain amount of time.

        10.             Modify the above solution to use “leasing” so that the client can renew the lease on the object to prevent it from being automatically released by the timer.

        11.             Modify the Object Pool system to take threading issues into account.

 

Factoring commonality

Applying the “once and only once” principle produces the most basic pattern of putting code that changes into a method.

This can be expressed two ways:

Strategy: choosing the algorithm at run-time

#[BT_231]#Strategy also adds a “Context” which can be a surrogate class that controls the selection and use of the particular strategy object—just like State! Here’s what it looks like:

//: strategy:StrategyPattern.java

package strategy;

import com.bruceeckel.util.*; // Arrays2.toString()

import junit.framework.*;

 

// The strategy interface:

interface FindMinima {

  // Line is a sequence of points:

  double[] algorithm(double[] line);

}

 

// The various strategies:

class LeastSquares implements FindMinima {

  public double[] algorithm(double[] line) {

    return new double[] { 1.1, 2.2 }; // Dummy

  }

}

 

class NewtonsMethod implements FindMinima {

  public double[] algorithm(double[] line) {

    return new double[] { 3.3, 4.4 }; // Dummy

  }

}

 

class Bisection implements FindMinima {

  public double[] algorithm(double[] line) {

    return new double[] { 5.5, 6.6 }; // Dummy

  }

}

 

class ConjugateGradient implements FindMinima {

  public double[] algorithm(double[] line) {

    return new double[] { 3.3, 4.4 }; // Dummy

  }

}

 

// The "Context" controls the strategy:

class MinimaSolver {

  private FindMinima strategy;

  public MinimaSolver(FindMinima strat) {

    strategy = strat;

  }

  double[] minima(double[] line) {

    return strategy.algorithm(line);

  }

  void changeAlgorithm(FindMinima newAlgorithm) {

    strategy = newAlgorithm;

  }

}

 

public class StrategyPattern extends TestCase  {

  MinimaSolver solver =

    new MinimaSolver(new LeastSquares());

  double[] line = {

    1.0, 2.0, 1.0, 2.0, -1.0,

    3.0, 4.0, 5.0, 4.0 };

  public void test() {

    System.out.println(

      Arrays2.toString(solver.minima(line)));

    solver.changeAlgorithm(new Bisection());

    System.out.println(

      Arrays2.toString(solver.minima(line)));

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(StrategyPattern.class);

  }

} ///:~

Note similarity with template method – TM claims distinction that it has more than one method to call, does things piecewise. However, it’s not unlikely that strategy object would have more than one method call; consider Shalloway’s order fulfullment system with country information in each strategy.

Strategy example from JDK: comparator objects.

Policy: generalized strategy

Although GoF says that Policy is just another name for strategy, their use of Strategy implicitly assumes a single method in the strategy object – that you’ve broken out your changing algorithm as a single piece of code.

Others[6] use Policy to mean an object that has multiple methods that may vary independently from class to class. This gives more flexibility than being restricted to a single method.

For example, a shipping policy for a product can be used to describe shipping issues for sending a package to various different countries. This may include the available methods of shipping, how to calculate postage or shipping cost, customs requirements and fees, and special handling costs. All these things may vary independently of each other, and more importantly you may need the information from each at different points in the shipping process.

It also seems generally useful to distinguish Strategies with single methods from Policies with multiple methods.

#[BT_232]#

#[BT_233]#

Template method

#[BT_86]#An application framework allows you to inherit from a class or set of classes and create a new application, reusing most of the code in the existing classes and overriding one or more methods in order to customize the application to your needs. A fundamental concept in the application framework is the Template Method which is typically hidden beneath the covers and drives the application by calling the various methods in the base class (some of which you have overridden in order to create the application).

#[BT_87]#For example, whenever you create an applet you’re using an application framework: you inherit from JApplet and then override init( ). The applet mechanism (which is a Template Method) does the rest by drawing the screen, handling the event loop, resizing, etc.

#[BT_88]#An important characteristic of the Template Method is that it is defined in the base class and cannot be changed. It’s sometimes a private method but it’s virtually always final. It calls other base-class methods (the ones you override) in order to do its job, but it is usually called only as part of an initialization process (and thus the client programmer isn’t necessarily able to call it directly).

//: templatemethod:TemplateMethod.java

// Simple demonstration of Template Method.

package templatemethod;

import junit.framework.*;

 

abstract class ApplicationFramework {

  public ApplicationFramework() {

    templateMethod(); // Dangerous!

  }

  abstract void customize1();

  abstract void customize2();

  final void templateMethod() {

    for(int i = 0; i < 5; i++) {

      customize1();

      customize2();

    }

  }

}

 

// Create a new "application":

class MyApp extends ApplicationFramework {

  void customize1() {

    System.out.print("Hello ");

  }

  void customize2() {

    System.out.println("World!");

  }

}

 

public class TemplateMethod extends TestCase  {

  MyApp app = new MyApp();

  public void test() {

    // The MyApp constructor does all the work.

    // This just makes sure it will complete

    // without throwing an exception.

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(TemplateMethod.class);

  }

} ///:~

#[BT_89]#

#[BT_90]#The base-class constructor is responsible for performing the necessary initialization and then starting the “engine” (the template method) that runs the application (in a GUI application, this “engine” would be the main event loop). The client programmer simply provides definitions for customize1( ) and customize2( ) and the “application” is ready to run.

Exercises

             1.             Create a framework that takes a list of file names on the command line. It opens each file except the last for reading, and the last for writing. The framework will process each input file using an undetermined policy and write the output to the last file. Inherit to customize this framework to create two separate applications:
1) Converts all the letters in each file to uppercase.
2) Searches the files for words given in the first file.

#[BT_91]#


Encapsulating creation

#[BT_203]#When you discover that you need to add new types to a system, the most sensible first step is to use polymorphism to create a common interface to those new types. This separates the rest of the code in your system from the knowledge of the specific types that you are adding. New types may be added without disturbing existing code … or so it seems. At first it would appear that the only place you need to change the code in such a design is the place where you inherit a new type, but this is not quite true. You must still create an object of your new type, and at the point of creation you must specify the exact constructor to use. Thus, if the code that creates objects is distributed throughout your application, you have the same problem when adding new types—you must still chase down all the points of your code where type matters. It happens to be the creation of the type that matters in this case rather than the use of the type (which is taken care of by polymorphism), but the effect is the same: adding a new type can cause problems.

#[BT_204]#The solution is to force the creation of objects to occur through a common factory rather than to allow the creational code to be spread throughout your system. If all the code in your program must go through this factory whenever it needs to create one of your objects, then all you must do when you add a new object is to modify the factory.

#[BT_205]#Since every object-oriented program creates objects, and since it’s very likely you will extend your program by adding new types, I suspect that factories may be the most universally useful kinds of design patterns.

Although only the Simple Factory Method is a true singleton, you’ll find that each specify factory class in the more general types of factories will only have a single instance.

Simple Factory method

#[BT_206]#As an example, let’s revisit the Shape system.  #[BT_207]#

#[BT_208]#One approach is to make the factory a static method of the base class:

//: factory:shapefact1:ShapeFactory1.java

// A simple static factory method.

package factory.shapefact1;

import java.util.*;

import junit.framework.*;

 

abstract class Shape {

  public abstract void draw();

  public abstract void erase();

  public static Shape factory(String type) {

    if(type.equals("Circle")) return new Circle();

    if(type.equals("Square")) return new Square();

    throw new RuntimeException(

      "Bad shape creation: " + type);

  }

}

 

class Circle extends Shape {

  Circle() {} // Package-access constructor

  public void draw() {

    System.out.println("Circle.draw");

  }

  public void erase() {

    System.out.println("Circle.erase");

  }

}

 

class Square extends Shape {

  Square() {} // Package-access constructor

  public void draw() {

    System.out.println("Square.draw");

  }

  public void erase() {

    System.out.println("Square.erase");

  }

}

 

public class ShapeFactory1 extends TestCase  {

  String shlist[] = { "Circle", "Square",

    "Square", "Circle", "Circle", "Square" };

  List shapes = new ArrayList();

  public void test() {

    Iterator it = Arrays.asList(shlist).iterator();

    while(it.hasNext())

      shapes.add(Shape.factory((String)it.next()));

    it = shapes.iterator();

    while(it.hasNext()) {

      Shape s = (Shape)it.next();

      s.draw();

      s.erase();

    }

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(ShapeFactory1.class);

  }

} ///:~

 

#[BT_209]#

#[BT_210]#The factory( ) takes an argument that allows it to determine what type of  Shape to create; it happens to be a String in this case but it could be any set of data. The factory( ) is now the only other code in the system that needs to be changed when a new type of Shape is added (the initialization data for the objects will presumably come from somewhere outside the system, and not be a hard-coded array as in the above example).

#[BT_211]#To encourage creation to only happen in the factory( ), the constructors for the specific types of Shape are give package access, so factory( ) has access to the constructors but they are not available outside the package.

Polymorphic factories

#[BT_212]#The static factory( ) method in the previous example forces all the creation operations to be focused in one spot, so that’s the only place you need to change the code. This is certainly a reasonable solution, as it throws a box around the process of creating objects. However, the Design Patterns book emphasizes that the reason for the Factory Method pattern is so that different types of factories can be subclassed from the basic factory (the above design is mentioned as a special case). However, the book does not provide an example, but instead just repeats the example used for the Abstract Factory (you’ll see an example of this in the next section). Here is ShapeFactory1.java modified so the factory methods are in a separate class as virtual functions. Notice also that the specific Shape classes are dynamically loaded on demand:

//: factory:shapefact2:ShapeFactory2.java

// Polymorphic factory methods.

package factory.shapefact2;

import java.util.*;

import junit.framework.*;

 

interface Shape {

  void draw();

  void erase();

}

 

abstract class ShapeFactory {

  protected abstract Shape create();

  private static Map factories = new HashMap();

  public static void

  addFactory(String id, ShapeFactory f) {

    factories.put(id, f);

  }

  // A Template Method:

  public static final

  Shape createShape(String id) {

    if(!factories.containsKey(id)) {

      try {

        // Load dynamically

        Class.forName("factory.shapefact2." + id);

      } catch(ClassNotFoundException e) {

        throw new RuntimeException(

          "Bad shape creation: " + id);

      }

      // See if it was put in:

      if(!factories.containsKey(id))

        throw new RuntimeException(

          "Bad shape creation: " + id);

    }

    return

      ((ShapeFactory)factories.get(id)).create();

  }

}

 

class Circle implements Shape {

  private Circle() {}

  public void draw() {

    System.out.println("Circle.draw");

  }

  public void erase() {

    System.out.println("Circle.erase");

  }

  private static class Factory

  extends ShapeFactory {

    protected Shape create() {

      return new Circle();

    }

  }

  static {

    ShapeFactory.addFactory(

      "Circle", new Factory());

  }

}

 

class Square implements Shape {

  private Square() {}

  public void draw() {

    System.out.println("Square.draw");

  }

  public void erase() {

    System.out.println("Square.erase");

  }

  private static class Factory

  extends ShapeFactory {

    protected Shape create() {

      return new Square();

    }

  }

  static {

    ShapeFactory.addFactory(

      "Square", new Factory());

  }

}

 

public class ShapeFactory2 extends TestCase  {

  String shlist[] = { "Circle", "Square",

    "Square", "Circle", "Circle", "Square" };

  List shapes = new ArrayList();

  public void test() {

    // This just makes sure it will complete

    // without throwing an exception.

    Iterator it = Arrays.asList(shlist).iterator();

    while(it.hasNext())

      shapes.add(

        ShapeFactory.createShape((String)it.next()));

    it = shapes.iterator();

    while(it.hasNext()) {

      Shape s = (Shape)it.next();

      s.draw();

      s.erase();

    }

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(ShapeFactory2.class);

  }

} ///:~

 

#[BT_213]#

#[BT_214]#Now the factory method appears in its own class, ShapeFactory, as the create( ) method. This is a protected method which means it cannot be called directly, but it can be overridden. The subclasses of Shape must each create their own subclasses of ShapeFactory and override the create( ) method to create an object of their own type. The actual creation of shapes is performed by calling ShapeFactory.createShape( ), which is a static method that uses the Map in ShapeFactory to find the appropriate factory object based on an identifier that you pass it. The factory is immediately used to create the shape object, but you could imagine a more complex problem where the appropriate factory object is returned and then used by the caller to create an object in a more sophisticated way. However, it seems that much of the time you don’t need the intricacies of the polymorphic factory method, and a single static method in the base class (as shown in ShapeFactory1.java) will work fine.

#[BT_215]#Notice that the ShapeFactory must be initialized by loading its Map with factory objects, which takes place in the static initialization clause of each of the Shape implementations. So to add a new type to this design you must inherit the type, create a factory, and add the static initialization clause to load the Map. This extra complexity again suggests the use of a static factory method if you don’t need to create individual factory objects.

Abstract factories

#[BT_216]#The Abstract Factory pattern looks like the factory objects we’ve seen previously, with not one but several factory methods. Each of the factory methods creates a different kind of object. The idea is that at the point of creation of the factory object, you decide how all the objects created by that factory will be used. The example given in Design Patterns implements portability across various graphical user interfaces (GUIs): you create a factory object appropriate to the GUI that you’re working with, and from then on when you ask it for a menu, button, slider, etc. it will automatically create the appropriate version of that item for the GUI. Thus you’re able to isolate, in one place, the effect of changing from one GUI to another.

#[BT_217]#As another example suppose you are creating a general-purpose gaming environment and you want to be able to support different types of games. Here’s how it might look using an abstract factory:

//: factory:Games.java

// An example of the Abstract Factory pattern.

package factory;

import junit.framework.*;

 

interface Obstacle {

  void action();

}

 

interface Player {

  void interactWith(Obstacle o);

}

 

class Kitty implements Player {

  public void interactWith(Obstacle ob) {

    System.out.print("Kitty has encountered a ");

    ob.action();

  }

}

 

class KungFuGuy implements Player {

  public void interactWith(Obstacle ob) {

    System.out.print("KungFuGuy now battles a ");

    ob.action();

  }

}

 

class Puzzle implements Obstacle {

  public void action() {

    System.out.println("Puzzle");

  }

}

 

class NastyWeapon implements Obstacle {

  public void action() {

    System.out.println("NastyWeapon");

  }

}

 

// The Abstract Factory:

interface GameElementFactory {

  Player makePlayer();

  Obstacle makeObstacle();

}

 

// Concrete factories:

class KittiesAndPuzzles

implements GameElementFactory {

  public Player makePlayer() {

    return new Kitty();

  }

  public Obstacle makeObstacle() {

    return new Puzzle();

  }

}

 

class KillAndDismember

implements GameElementFactory {

  public Player makePlayer() {

    return new KungFuGuy();

  }

  public Obstacle makeObstacle() {

    return new NastyWeapon();

  }

}

 

class GameEnvironment {

  private GameElementFactory gef;

  private Player p;

  private Obstacle ob;

  public GameEnvironment(

    GameElementFactory factory) {

    gef = factory;

    p = factory.makePlayer();

    ob = factory.makeObstacle();

  }

  public void play() { p.interactWith(ob); }

}

 

public class Games extends TestCase  {

  GameElementFactory

    kp = new KittiesAndPuzzles(),

    kd = new KillAndDismember();

  GameEnvironment

    g1 = new GameEnvironment(kp),

    g2 = new GameEnvironment(kd);

  // These just ensure no exceptions are thrown:

  public void test1() { g1.play(); }

  public void test2() { g2.play(); }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(Games.class);

  }

} ///:~

#[BT_218]#

#[BT_219]#In this environment, Player objects interact with Obstacle objects, but there are different types of players and obstacles depending on what kind of game you’re playing. You determine the kind of game by choosing a particular GameElementFactory, and then the GameEnvironment controls the setup and play of the game. In this example, the setup and play is very simple, but those activities (the initial conditions and the state change) can determine much of the game’s outcome. Here, GameEnvironment is not designed to be inherited, although it could very possibly make sense to do that.

#[BT_220]#This also contains examples of Double Dispatching and the Factory Method, both of which will be explained later.

Exercises

             1.             Add a class Triangle to ShapeFactory1.java

             2.             Add a class Triangle to ShapeFactory2.java

             3.             Add a new type of GameEnvironment called GnomesAndFairies to Games.java

             4.             Modify ShapeFactory2.java so that it uses an Abstract Factory to create different sets of shapes (for example, one particular type of factory object creates “thick shapes,” another creates “thin shapes,” but each factory object can create all the shapes: circles, squares, triangles etc.).

#[BT_221]#

#[BT_222]#


Specialized creation

Prototype

Objects are created by cloning a prototypical instance. An example of this appears in the “Pattern Refactoring” chapter.

Builder

The goal of builder is to separate the construction from the “representation,” to allow multiple different representations. The construction process stays the same, but the resulting object has different possible representations. GoF points out that the main difference with Abstract Factory is that a Builder creates the object step-by-step, so the fact that the creation process is spread out in time seems to be important. In addition, it seems that the “director” gets a stream of pieces that it passes to the Builder, and each piece is used to perform one of the steps in the build process.

One example given in GoF is that of a text format converter. The incoming format is RTF, and once it is parsed the directives are passed to the text converter, which may be implemented in different ways depending on whether the resulting format is ASCII, TeX, or a “GUI Text Widget.” Although the resulting “object” (the entire converted text file) is created over time, if you consider the conversion of each RTF directive to be an object, this feels to me a little more like Bridge, because the specific types of converters extend the interface of the base class. Also, the general solution to the problem would allow multiple readers on the “front end” and multiple converters on the “back end,” which is a primary characteristic of Bridge.

To me, the fact that Builder has multiple steps in creating an object, and those steps are accessed externally to the Builder object, is the essence of what distinguishes it (structurally, anyway) from a regular factory.  However, GoF emphasizes that you’re able to create different representations using the same process. They never define exactly what they mean by representation. (Does the “representation” involve an object that is too large? Would the need for Builder vanish if the representation was broken into smaller objects?)

The other example in GoF creates a maze object and adds rooms within the maze and doors within the rooms. Thus it is a multistep process, but alas, the different “representations” are the “Standard” and “Complex” mazes – not really different kinds of mazes, but instead different complexity. I think I would have tried to create one maze builder that could handle arbitrarily complex mazes. The final variation of the maze builder is something that doesn’t create mazes at all, but instead counts the rooms in an existing maze.

Neither the RTF converter nor the Mazebuilder example makes an overwhelmingly compelling case for Builder. Readers have suggested that the output of the Sax XML parser, and standard compiler parsers, might naturally be fed into a Builder.

Here’s an example that may be a little more compelling, or at least give more of an idea of what Builder is trying to do. Media may be constructed into different representations, in this case books, magazines and web sites. The example argues that the steps involved are the same, and so can be abstracted into the director class.

//: builder:BuildMedia.java

// Example of the Builder pattern

package builder;

import java.util.*;

import junit.framework.*;

 

// Different "representations" of media:

class Media extends ArrayList {}

class Book extends Media {}

class Magazine extends Media {}

class WebSite extends Media {}

 

// ... contain different kinds of media items:

class MediaItem {

  private String s;

  public MediaItem(String s) { this.s = s; }

  public String toString() { return s; }

}

class Chapter extends MediaItem {

  public Chapter(String s) { super(s); }

}

class Article extends MediaItem {

  public Article(String s) { super(s); }

}

class WebItem extends MediaItem {

  public WebItem(String s) { super(s); }

}

 

// ... but use the same basic construction steps:

class MediaBuilder {

  public void buildBase() {}

  public void addMediaItem(MediaItem item) {}

  public Media getFinishedMedia() { return null; }

}

 

class BookBuilder extends MediaBuilder {

  private Book b;

  public void buildBase() {

    System.out.println("Building book framework");

    b = new Book();

  }

  public void addMediaItem(MediaItem chapter) {

    System.out.println("Adding chapter " + chapter);

    b.add(chapter);

  }

  public Media getFinishedMedia() { return b; }

 

class MagazineBuilder extends MediaBuilder {

  private Magazine m;

  public void buildBase() {

    System.out.println("Building magazine framework");

    m = new Magazine();

  }

  public void addMediaItem(MediaItem article) {

    System.out.println("Adding article " + article);

    m.add(article);

  }

  public Media getFinishedMedia() { return m; }

 

class WebSiteBuilder extends MediaBuilder {

  private WebSite w;

  public void buildBase() {

    System.out.println("Building web site framework");

    w = new WebSite();

  }

  public void addMediaItem(MediaItem webItem) {

    System.out.println("Adding web item " + webItem);

    w.add(webItem);

  }

  public Media getFinishedMedia() { return w; }

 

class MediaDirector { // a.k.a. "Context"

  private MediaBuilder mb;

  public MediaDirector(MediaBuilder mb) {

    this.mb = mb; // Strategy-ish

  }

  public Media produceMedia(List input) {

    mb.buildBase();

    for(Iterator it = input.iterator(); it.hasNext();)

      mb.addMediaItem((MediaItem)it.next());

    return mb.getFinishedMedia();

  }

};

 

public class BuildMedia extends TestCase {

  private List input = Arrays.asList(new MediaItem[] {

    new MediaItem("item1"), new MediaItem("item2"),

    new MediaItem("item3"), new MediaItem("item4"),

  });

  public void testBook() {

    MediaDirector buildBook =

      new MediaDirector(new BookBuilder());

    Media book = buildBook.produceMedia(input);

    String result = "book: " + book;

    System.out.println(result);

    assertEquals(result,

      "book: [item1, item2, item3, item4]");

  }

  public void testMagazine() {

    MediaDirector buildMagazine =

      new MediaDirector(new MagazineBuilder());

    Media magazine = buildMagazine.produceMedia(input);

    String result = "magazine: " + magazine;

    System.out.println(result);

    assertEquals(result,

      "magazine: [item1, item2, item3, item4]");

  }

  public void testWebSite() {

    MediaDirector buildWebSite =

      new MediaDirector(new WebSiteBuilder());

    Media webSite = buildWebSite.produceMedia(input);

    String result = "web site: " + webSite;

    System.out.println(result);

    assertEquals(result,

      "web site: [item1, item2, item3, item4]");

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(BuildMedia.class);

  }

} ///:~

 

Note that in some ways this could be seen as a more complicated State pattern, since the behavior of the director depends on what type of builder you use. Instead of simply forwarding the requests through to the underlying State object, however, the director has a sequence of operations to perform, and it uses the State object as a Policy to fulfill its job. Thus, Builder could be described as using a Policy to create objects.

Exercises

             1.             Break a text file up into an input stream of words (consider using regular expressions for this). Create one Builder that puts the words into a java.util.TreeSet, and another that produces a java.util.HashMap containing words and occurrences of those words (that is, it does a word count).

Too many

Flyweight: too many objects

The odd thing about flyweight, in the company of the other design patterns, is that it’s a performance hack. It’s generally ideal to simply make an object for every item in your system, but some problems generate a prohibitive number of objects, which may result in excessive slowness or running out of memory.

Flyweight solves this problem by reducing the number of objects. To do this, you externalize some of the data in an object, so that you can pretend that you have more objects than you really do. However, this adds complexity to the interface for using such objects, because you must pass in additional information to method calls in order to tell the method how to find the externalized information.

As a very simple example, consider a DataPoint object that holds an int, a float, and an id that carries the object number. Suppose you need to create a million of these objects, and then manipulate them, like so:

//: flyweight:ManyObjects.java

 

class DataPoint {

  private static int count = 0;

  private int id = count++;

  private int i;

  private float f;

  public int getI() { return i; }

  public void setI(int i) { this.i = i; }

  public float getF() { return f; }

  public void setF(float f) { this.f = f; }

  public String toString() {

    return "id: " + id + ", i = " + i + ", f = " + f;

  }

}

 

public class ManyObjects {

  static final int size = 1000000;

  public static void main(String[] args) {

    DataPoint[] array = new DataPoint[size];

    for(int i = 0; i < array.length; i++)

      array[i] = new DataPoint();

    for(int i = 0; i < array.length; i++) {

      DataPoint dp = array[i];

      dp.setI(dp.getI() + 1);

      dp.setF(47.0f);

    }

    System.out.println(array[size -1]);

  }

} ///:~

 

Depending on your computer, this program may take several seconds to run. More complex objects and more involved operations may cause the overhead to become untenable. To solve the problem the DataPoint can be reduced from a million objects to one object by externalizing the data held in the DataPoint:

//: flyweight:FlyWeightObjects.java

 

class ExternalizedData {

  static final int size = 5000000;

  static int[] id = new int[size];

  static int[] i = new int[size];

  static float[] f = new float[size];

  static {

    for(int i = 0; i < size; i++)

      id[i] = i;

  }

}

 

class FlyPoint {

  private FlyPoint() {}

  public static int getI(int obnum) {

    return ExternalizedData.i[obnum];

  }

  public static void setI(int obnum, int i) {

    ExternalizedData.i[obnum] = i;

  }

  public static float getF(int obnum) {

    return ExternalizedData.f[obnum];

  }

  public static void setF(int obnum, float f) {

    ExternalizedData.f[obnum] = f;

  }

  public static String str(int obnum) {

    return "id: " +

      ExternalizedData.id[obnum] +

      ", i = " +

      ExternalizedData.i[obnum] +

      ", f = " +

      ExternalizedData.f[obnum];

  }

}

 

public class FlyWeightObjects {

  public static void main(String[] args) {

    for(int i = 0; i < ExternalizedData.size; i++) {

      FlyPoint.setI(i, FlyPoint.getI(i) + 1);

      FlyPoint.setF(i, 47.0f);

    }

    System.out.println(

      FlyPoint.str(ExternalizedData.size -1));

  }

} ///:~

 

Since all the data is now in ExternalizedData, each call to a FlyPoint method must include the index into ExternalizedData. For consistency, and to remind the reader of the similarity with the implicit this pointer in method calls, the “this index” is passed in as the first argument.

Naturally, it’s worth repeating admonishments against premature optimization. “First make it work, then make it fast – if you have to.” Also, a profiler is the tool to use for discovering performance bottlenecks, not guesswork.

Decorator: too many classes

The use of layered objects to dynamically and transparently add responsibilities to individual objects is referred to as the decorator pattern.

#[BT_155]#Used when subclassing creates too many (& inflexible) classes

#[BT_156]#All decorators that wrap around the original object must have the same basic interface

#[BT_157]#Dynamic proxy/surrogate?

#[BT_158]#This accounts for the odd inheritance structure

#[BT_159]#Tradeoff: coding is more complicated when using decorators

Basic decorator structure

#[BT_160]#

A coffee example

#[BT_161]#Consider going down to the local coffee shop, BeanMeUp, for a coffee.  There are typically many different drinks on offer -- espressos, lattes, teas, iced coffees, hot chocolate to name a few, as well as a number of extras (which cost extra too) such as whipped cream or an extra shot of espresso. You can also make certain changes to your drink at no extra cost, such as asking for decaf coffee instead of regular coffee.

#[BT_162]#Quite clearly if we are going to model all these drinks and combinations, there will be sizeable class diagrams. So for clarity we will only consider a subset of the coffees: Espresso, Espresso Con Panna, Café Late, Cappuccino and Café Mocha. We'll include 2 extras - whipped cream ("whipped") and an extra shot of espresso; and three changes - decaf, steamed milk ("wet") and foamed milk ("dry").

Class for each combination

#[BT_163]#One solution is to create an individual class for every combination. Each class describes the drink and is responsible for the cost etc. The resulting menu is huge, and a part of the class diagram would look something like this:

#[BT_164]#

#[BT_165]#Here is one of the combinations, a simple implementation of a Cappuccino:

class Cappuccino {

  private float cost = 1;

  private String description = "Cappucino";

  public float getCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

#[BT_166]#

#[BT_167]#The key to using this method is to find the particular combination you want.  So, once you've found the drink you would like, here is how you would use it, as shown in the CoffeeShop class in the following code:

//: decorator:nodecorators:CoffeeShop.java

// Coffee example with no decorators

package decorator.nodecorators;

import junit.framework.*;

 

class Espresso {}

class DoubleEspresso {}

class EspressoConPanna {}

 

class Cappuccino {

  private float cost = 1;

  private String description = "Cappucino";

  public float getCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

class CappuccinoDecaf {}

class CappuccinoDecafWhipped {}

class CappuccinoDry {}

class CappuccinoDryWhipped {}

class CappuccinoExtraEspresso {}

class CappuccinoExtraEspressoWhipped {}

class CappuccinoWhipped {}

 

class CafeMocha {}

class CafeMochaDecaf {}

class CafeMochaDecafWhipped {

  private float cost = 1.25f;

  private String description =

    "Cafe Mocha decaf whipped cream";

  public float getCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

class CafeMochaExtraEspresso {}

class CafeMochaExtraEspressoWhipped {}

class CafeMochaWet {}

class CafeMochaWetWhipped {}

class CafeMochaWhipped {}

 

class CafeLatte {}

class CafeLatteDecaf {}

class CafeLatteDecafWhipped {}

class CafeLatteExtraEspresso {}

class CafeLatteExtraEspressoWhipped {}

class CafeLatteWet {}

class CafeLatteWetWhipped {}

class CafeLatteWhipped {}

 

public class CoffeeShop extends TestCase  {

  public void testCappuccino() {

    // This just makes sure it will complete

    // without throwing an exception.

    // Create a plain cappuccino

    Cappuccino cappuccino = new Cappuccino();

    System.out.println(cappuccino.getDescription()

      + ": $" + cappuccino.getCost());

  }

  public void testCafeMocha() {

    // This just makes sure it will complete

    // without throwing an exception.

    // Create a decaf cafe mocha with whipped

    // cream

    CafeMochaDecafWhipped cafeMocha =

      new CafeMochaDecafWhipped();

    System.out.println(cafeMocha.getDescription()

      + ": $" + cafeMocha.getCost());

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(CoffeeShop.class);

  }

} ///:~

#[BT_168]#

#[BT_169]#And here is the corresponding output:

Cappucino: $1.0

Cafe Mocha decaf whipped cream: $1.25

#[BT_170]#

#[BT_171]#You can see that creating the particular combination you want is easy, since you are just creating an instance of a class. However, there are a number of problems with this approach. Firstly, the combinations are fixed statically so that any combination a customer may wish to order needs to be created up front. Secondly, the resulting menu is so huge that finding your particular combination is difficult and time consuming.

The decorator approach

#[BT_172]#Another approach would be to break the drinks down into the various components such as espresso and foamed milk, and then let the customer combine the components to describe a particular coffee.

#[BT_173]#In order to do this programmatically, we use the Decorator pattern.  A Decorator adds responsibility to a component by wrapping it, but the Decorator conforms to the interface of the component it encloses, so the wrapping is transparent. Decorators can also be nested without the loss of this transparency.

#[BT_174]#

#[BT_175]#Methods invoked on the Decorator can in turn invoke methods in the component, and can of course perform processing before or after the invocation.

#[BT_176]#So if we added getTotalCost() and getDescription() methods to the DrinkComponent interface, an Espresso looks like this:

class Espresso extends Decorator {

  private float cost = 0.75f;

  private String description = " espresso";

  public Espresso(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return component.getTotalCost() + cost;

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

#[BT_177]#

#[BT_178]#You combine the components to create a drink as follows, as shown in the code below:

//: decorator:alldecorators:CoffeeShop2.java

// Coffee example using decorators

package decorator.alldecorators;

import junit.framework.*;

 

interface DrinkComponent {

  String getDescription();

  float getTotalCost();

}

 

class Mug implements DrinkComponent {

  public String getDescription() {

    return "mug";

  }

  public float getTotalCost() {

    return 0;

  }

}

 

abstract class Decorator implements DrinkComponent

{

  protected DrinkComponent component;

  Decorator(DrinkComponent component) {

    this.component = component;

  }

  public float getTotalCost() {

    return component.getTotalCost();

  }

  public abstract String getDescription();

}

 

class Espresso extends Decorator {

  private float cost = 0.75f;

  private String description = " espresso";

  public Espresso(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return component.getTotalCost() + cost;

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

 

class Decaf extends Decorator {

  private String description = " decaf";

  public Decaf(DrinkComponent component) {

    super(component);

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

 

class FoamedMilk extends Decorator {

  private float cost = 0.25f;

  private String description = " foamed milk";

  public FoamedMilk(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return component.getTotalCost() + cost;

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

 

class SteamedMilk extends Decorator {

  private float cost = 0.25f;

  private String description = " steamed milk";

  public SteamedMilk(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return component.getTotalCost() + cost;

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

 

class Whipped extends Decorator {

  private float cost = 0.25f;

  private String description = " whipped cream";

  public Whipped(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return component.getTotalCost() + cost;

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

 

class Chocolate extends Decorator {

  private float cost = 0.25f;

  private String description = " chocolate";

  public Chocolate(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return component.getTotalCost() + cost;

  }

  public String getDescription() {

    return component.getDescription() +

      description;

  }

}

 

public class CoffeeShop2 extends TestCase  {

  public void testCappuccino() {

    // This just makes sure it will complete

    // without throwing an exception.

    // Create a plain cappucino

    DrinkComponent cappuccino = new Espresso(

      new FoamedMilk(new Mug()));

    System.out.println(cappuccino.

      getDescription().trim() + ": $" +

      cappuccino.getTotalCost());

  }

  public void testCafeMocha() {

    // This just makes sure it will complete

    // without throwing an exception.

    // Create a decaf cafe mocha with whipped

    // cream

    DrinkComponent cafeMocha = new Espresso(

      new SteamedMilk(new Chocolate(new Whipped(

      new Decaf(new Mug())))));

    System.out.println(cafeMocha.getDescription().

      trim() + ": $" + cafeMocha.getTotalCost());

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(CoffeeShop2.class);

  }

} ///:~

#[BT_179]#

#[BT_180]#This approach would certainly provide the most flexibility and the smallest menu. You have a small number of components to choose from, but assembling the description of the coffee then becomes rather arduous.

#[BT_181]#If you want to describe a plain cappuccino, you create it with

new Espresso(new FoamedMilk(new Mug()))

#[BT_182]#Creating a decaf Café Mocha with whipped cream requires an even longer description.

Compromise

#[BT_183]#The previous approach takes too long to describe a coffee. There will also be certain combinations that you will describe regularly, and it would be convenient to have a quick way of describing them.

#[BT_184]#The 3rd approach is a mixture of the first 2 approaches, and combines flexibility with ease of use. This compromise is achieved by creating a reasonably sized menu of basic selections, which would often work exactly as they are, but if you wanted to decorate them (whipped cream, decaf etc.) then you would use decorators to make the modifications. This is the type of menu you are presented with in most coffee shops.

#[BT_185]#

#[BT_186]#Here is how to create a basic selection, as well as a decorated selection:

//: decorator:compromise:CoffeeShop3.java

// Coffee example with a compromise of basic

// combinations and decorators

package decorator.compromise;

import junit.framework.*;

 

interface DrinkComponent {

  float getTotalCost();

  String getDescription();

}

 

class Espresso implements DrinkComponent {

  private String description = "Espresso";

  private float cost = 0.75f;

  public float getTotalCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

 

class EspressoConPanna implements DrinkComponent {

  private String description = "EspressoConPare";

  private float cost = 1;

  public float getTotalCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

 

class Cappuccino implements DrinkComponent {

  private float cost = 1;

  private String description = "Cappuccino";

  public float getTotalCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

 

class CafeLatte implements DrinkComponent {

  private float cost = 1;

  private String description = "Cafe Late";

  public float getTotalCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

 

class CafeMocha implements DrinkComponent {

  private float cost = 1.25f;

  private String description = "Cafe Mocha";

  public float getTotalCost() {

    return cost;

  }

  public String getDescription() {

    return description;

  }

}

 

abstract class Decorator implements DrinkComponent {

  protected DrinkComponent component;

  public Decorator(DrinkComponent component) {

    this.component = component;

  }

  public float getTotalCost() {

    return component.getTotalCost();

  }

  public String getDescription() {

    return component.getDescription();

  }

}

 

class ExtraEspresso extends Decorator {

  private float cost = 0.75f;

  public ExtraEspresso(DrinkComponent component) {

    super(component);

  }

  public String getDescription() {

    return component.getDescription() +

      " extra espresso";

  }

  public float getTotalCost() {

    return cost + component.getTotalCost();

  }

}

 

class Whipped extends Decorator {

  private float cost = 0.50f;

  public Whipped(DrinkComponent component) {

    super(component);

  }

  public float getTotalCost() {

    return cost + component.getTotalCost();

  }

  public String getDescription() {

    return component.getDescription() +

      " whipped cream";

  }

}

 

class Decaf extends Decorator{

  public Decaf(DrinkComponent component) {

    super(component);

  }

  public String getDescription() {

    return component.getDescription() + " decaf";

  }

}

 

class Dry extends Decorator {

  public Dry(DrinkComponent component) {

    super(component);

  }

  public String getDescription() {

    return component.getDescription() +

      " extra foamed milk";

  }

}

 

class Wet extends Decorator {

  public Wet(DrinkComponent component) {

    super(component);

  }

  public String getDescription() {

    return component.getDescription() +

      " extra steamed milk";

  }

}

 

public class CoffeeShop3 extends TestCase  {

  public void testCappuccino() {

    // This just makes sure it will complete

    // without throwing an exception.

    // Create a plain cappucino

    DrinkComponent cappuccino = new Cappuccino();

    System.out.println(cappuccino.getDescription()

      + ": $" + cappuccino.getTotalCost());

  }

  public void testCafeMocha() {

    // This just makes sure it will complete

    // without throwing an exception.

    // Create a decaf cafe mocha with whipped

    // cream

    DrinkComponent cafeMocha = new Whipped(

      new Decaf(new CafeMocha()));

    System.out.println(cafeMocha.getDescription()

      + ": $" + cafeMocha.getTotalCost());

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(CoffeeShop3.class);

  }

} ///:~

#[BT_187]#

#[BT_188]#You can see that creating a basic selection is quick and easy, which makes sense since they will be described regularly.  Describing a decorated drink is more work than when using a class per combination, but clearly less work than when only using decorators.

#[BT_189]#The final result is not too many classes, but not too many decorators either. Most of the time it's possible to get away without using any decorators at all, so we have the benefits of both approaches.

Other considerations

#[BT_190]#What happens if we decide to change the menu at a later stage, such as by adding a new type of drink? If we had used the class per combination approach, the effect of adding an extra such as syrup would be an exponential growth in the number of classes. However, the implications to the all decorator or compromise approaches are the same - one extra class is created.

#[BT_191]#How about the effect of changing the cost of steamed milk and foamed milk, when the price of milk goes up? Having a class for each combination means that you need to change a method in each class, and thus maintain many classes. By using decorators, maintenance is reduced by defining the logic in one place.

Exercises

             1.             Add a Syrup class to the decorator approach described above. Then create a Café Latte (you'll need to use steamed milk with an espresso) with syrup.

             2.             Repeat Exercise 1 for the compromise approach.

             3.             Create a simple decorator system that models the fact that some birds fly and some don’t, some swim and some don’t, and some do both.

             4.             Implement the decorator pattern to create a Pizza restaurant, which has a set menu of choices as well as the option to design your own pizza.  Follow the compromise approach to create a menu consisting of a Margherita, Hawaiian, Regina, and Vegetarian pizzas, with toppings (decorators) of Garlic, Olives, Spinach, Avocado, Feta and Pepperdews. Create a Hawaiian pizza, as well as a Margherita decorated with Spinach, Feta, Pepperdews and Olives.

             5.             About Decorator, the Design Patterns book states: “With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them.” Implement the coffee decoration system to allow this “simple” detaching of a responsibility from the middle of the list of decorators of a complex coffee beverage.

#[BT_192]#


Connecting different types

Adapter

Adapter takes one type and produces an interface to some other type. #[BT_240]#When you’ve got this, and you need that, Adapter solves the problem. The only requirement is to produce a that, and there are a number of ways you can accomplish this adaptation.

//: adapter:SimpleAdapter.java

// "Object Adapter" from GoF diagram

package adapter;

import junit.framework.*;

 

class Target {

  public void request() {}

}

 

class Adaptee {

  public void specificRequest() {

    System.out.println("Adaptee: SpecificRequest");

  }

}

 

class Adapter extends Target {

  private Adaptee adaptee;

  public Adapter(Adaptee a) {

    adaptee = a;

  }

  public void request() {

    adaptee.specificRequest();

  }

}

 

public class SimpleAdapter extends TestCase  {

  Adaptee a = new Adaptee();

  Target t = new Adapter(a);

  public void test() {

    t.request();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(SimpleAdapter.class);

  }

} ///:~

 

//: adapter:AdapterVariations.java

// Variations on the Adapter pattern.

package adapter;

import junit.framework.*;

 

class WhatIHave {

  public void g() {}

  public void h() {}

}

 

interface WhatIWant {

  void f();

}

 

class SurrogateAdapter implements WhatIWant {

  WhatIHave whatIHave;

  public SurrogateAdapter(WhatIHave wih) {

    whatIHave = wih;

  }

  public void f() {

    // Implement behavior using

    // methods in WhatIHave:

    whatIHave.g();

    whatIHave.h();

  }

}

 

class WhatIUse {

  public void op(WhatIWant wiw) {

    wiw.f();

  }

}

 

// Approach 2: build adapter use into op():

class WhatIUse2 extends WhatIUse {

  public void op(WhatIHave wih) {

    new SurrogateAdapter(wih).f();

  }

}

 

// Approach 3: build adapter into WhatIHave:

class WhatIHave2 extends WhatIHave

implements WhatIWant {

  public void f() {

    g();

    h();

  }

}

 

// Approach 4: use an inner class:

class WhatIHave3 extends WhatIHave {

  private class InnerAdapter implements WhatIWant{

    public void f() {

      g();

      h();

    }

  }

  public WhatIWant whatIWant() {

    return new InnerAdapter();

  }

}

 

public class AdapterVariations extends TestCase  {

  WhatIUse whatIUse = new WhatIUse();

  WhatIHave whatIHave = new WhatIHave();

  WhatIWant adapt= new SurrogateAdapter(whatIHave);

  WhatIUse2 whatIUse2 = new WhatIUse2();

  WhatIHave2 whatIHave2 = new WhatIHave2();

  WhatIHave3 whatIHave3 = new WhatIHave3();

  public void test() {

    whatIUse.op(adapt);

    // Approach 2:

    whatIUse2.op(whatIHave);

    // Approach 3:

    whatIUse.op(whatIHave2);

    // Approach 4:

    whatIUse.op(whatIHave3.whatIWant());

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(AdapterVariations.class);

  }

} ///:~

#[BT_241]#

#[BT_242]#I’m taking liberties with the term “proxy” here, because in Design Patterns they assert that a proxy must have an identical interface with the object that it is a surrogate for. However, if you have the two words together: “proxy adapter,” it is perhaps more reasonable.

Bridge

While researching Bridge, I discovered that it appears to be the most poorly-described pattern in the GoF. I began to come to this conclusion when reading Alan Shalloway’s chapter on Bridge in his book Design Patterns Explained – he begins by pointing out that the description in GoF left him quite unenlightened.

At a conference, I talked to two people who had written about and were giving talks on design patterns, including Bridge. In two separate discussions I got completely different perspectives on the structure of Bridge.

Armed with misinformation, I delved back into the GoF and realized that neither of the above perspectives agreed with the book. I also found that the book did a miserable job of describing Bridge, except in one place – not the general structure chart describing the pattern, which wasn’t helpful, but in the structure chart describing their specific example. Only if you stare at that for a bit does Bridge begin to make sense.

An important feature to understand when looking at Bridge is that it is often a construct that is used to help you write code. You may choose the objects you use for a particular situation at compile-time or runtime, but the goal of Bridge is to allow you to structure your code so that you can easily add new kinds of front-end objects which are implemented with functionality in new kinds of back-end objects. Thus, both front-end and back-end can vary independently of each other.

The front-end classes can have completely different interfaces from each other, and typically do. What they have in common is that they can implement their functionality using facilities from any number of different back-end objects. The back-end objects also don’t have the same interface. The only thing the back-end objects must have in common is that they implement the same kind of functionality – for example, a group of different ways to implement a graphics library or a set of different data-storage solutions.

Bridge is really a code-organization tool that allows you to add in any number of new front-end services that implement their operations by delegating to any number of back-end options. Using Bridge, you can accomplish this without the normal combinatorial explosion of possibilities that would otherwise occur. But keep in mind that the vector of change with Bridge is typically happening at coding time: it keeps your code organized when you are dealing with an increasing number of options for implementing functionality.

Here’s an example whose sole purpose is to demonstrate the structure of Bridge (it implements the above diagram):

//: bridge:BridgeStructure.java

// A demonstration of the structure and operation

// of the Bridge Pattern.

package bridge;

import junit.framework.*;

 

class Abstraction {

  private Implementation implementation;

  public Abstraction(Implementation imp) {

    implementation = imp;

  }

  // Abstraction used by the various front-end

  // objects in order to implement their

  // different interfaces.

  public void service1() {

    // Implement this feature using some

    // combination of back-end implementation:

    implementation.facility1();

    implementation.facility2();

  }

  public void service2() {

    // Implement this feature using some other

    // combination of back-end implementation:

    implementation.facility2();

    implementation.facility3();

  }

  public void service3() {

    // Implement this feature using some other

    // combination of back-end implementation:

    implementation.facility1();

    implementation.facility2();

    implementation.facility4();

  }

  // For use by subclasses:

  protected Implementation getImplementation() {

    return implementation;

  }

}

 

class ClientService1 extends Abstraction {

  public ClientService1(Implementation imp) { super(imp); }

  public void serviceA() {

    service1();

    service2();

  }

  public void serviceB() {

    service3();

  }

}

 

class ClientService2 extends Abstraction {

  public ClientService2(Implementation imp) { super(imp); }

  public void serviceC() {

    service2();

    service3();

  }

  public void serviceD() {

    service1();

    service3();

  }

  public void serviceE() {

    getImplementation().facility3();

  }

}

 

interface Implementation {

  // The common implementation provided by the

  // back-end objects, each in their own way.

  void facility1();

  void facility2();

  void facility3();

  void facility4();

}

 

class Library1 {

  public void method1() {

    System.out.println("Library1.method1()");

  }

  public void method2() {

    System.out.println("Library1.method2()");

  }

}

 

class Library2 {

  public void operation1() {

    System.out.println("Library2.operation1()");

  }

  public void operation2() {

    System.out.println("Library2.operation2()");

  }

  public void operation3() {

    System.out.println("Library2.operation3()");

  }

}

 

class Implementation1 implements Implementation {

  // Each facility delegates to a different library

  // in order to fulfill the obligations.

  private Library1 delegate = new Library1();

  public void facility1() {

    System.out.println("Implementation1.facility1");

    delegate.method1();

  }

  public void facility2() {

    System.out.println("Implementation1.facility2");

    delegate.method2();

  }

  public void facility3() {

    System.out.println("Implementation1.facility3");

    delegate.method2();

    delegate.method1();

  }

  public void facility4() {

    System.out.println("Implementation1.facility4");

    delegate.method1();

  }

}

 

class Implementation2 implements Implementation {

  private Library2 delegate = new Library2();

  public void facility1() {

    System.out.println("Implementation2.facility1");

    delegate.operation1();

  }

  public void facility2() {

    System.out.println("Implementation2.facility2");

    delegate.operation2();

  }

  public void facility3() {

    System.out.println("Implementation2.facility3");

    delegate.operation3();

  }

  public void facility4() {

    System.out.println("Implementation2.facility4");

    delegate.operation1();

  }

}

 

public class BridgeStructure extends TestCase  {

  public void test1() {

    // Here, the implementation is determined by

    // the client at creation time:

    ClientService1 cs1 =

      new ClientService1(new Implementation1());

    cs1.serviceA();

    cs1.serviceB();

  }

  public void test2() {

    ClientService1 cs1 =

      new ClientService1(new Implementation2());

    cs1.serviceA();

    cs1.serviceB();

  }

  public void test3() {

    ClientService2 cs2 =

      new ClientService2(new Implementation1());

    cs2.serviceC();

    cs2.serviceD();

    cs2.serviceE();

  }

  public void test4() {

    ClientService2 cs2 =

      new ClientService2(new Implementation2());

    cs2.serviceC();

    cs2.serviceD();

    cs2.serviceE();

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(BridgeStructure.class);

  } 

} ///:~

 

The front-end base class provides the operations used to fulfill the front-end derived classes, in terms of the methods of the back-end base class. Thus, any back-end derived class can be used to perform the operations needed by the front-end class. Notice that the bridging happens in this sequence of steps, each of which is providing a layer of abstraction. Here, Implementation is defined as an interface to emphasize that all the functionality is implemented in the back-end derived classes, and none in the back-end base.

The back-end derived classes perform the operations defined in the base class by delegating to objects (of class Library1 and Library2, in this case) that typically have radically different interfaces, but somehow provide the same functionality (this is one of the important objectives of Bridge). Effectively, each of the back-end implementations is an adapter to a different library or tool used to implement the desired functionality in a different way.

Exercises

             1.             Modify BridgeStructure.java so that the implementations are chosen using a factory.

             2.             Modify BridgeStructure.java to use delegation instead of inheritance on the front end. What benefits and drawbacks do you see by using delegation rather than inheritance?

             3.             Create an example of Bridge with an abstraction that is an associative array. This allows you to fetch elements by passing in a key Object. The constructor provides an initial set of key-value pairs which are placed in an array. As long as you only fetch elements, the array is used, but as soon as you set a new key-value pair, the implementation is switched to a map.

             4.             Use a bridge along with the collections in java.util.collections to create stack and queue classes using an ArrayList. After you get the system working, add a double-ended queue class. Now add a LinkedList as an implementation. These steps will demonstrate how Bridge allows you to add new front-end classes and new back-end classes in your code, with minimal impact.

             5.             Create a Bridge that provides a connection between various kinds of bookkeeping programs (along with their interfaces and data formats) and different banks (which provide different kinds of services and interfaces).

#[BT_250]#

#[BT_251]#


Flexible structure

Composite

The important thing here is that all elements in the part-whole have operations, and that performing an operation on a node/composite also performs that operation on any children of that node/composite. GoF includes implementation details of containment and visitation of children in the interface of the base class, but this doesn’t seem necessary. In the following example, the Composite class simply inherits ArrayList in order to gain its containment abilities.

//: composite:CompositeStructure.java

package composite;

import java.util.*;

import junit.framework.*;

 

interface Component {

  void operation();

}

 

class Leaf implements Component {

  private String name;

  public Leaf(String name) { this.name = name; }

  public String toString() { return name; }

  public void operation() {

    System.out.println(this);

  }

}

 

class Node extends ArrayList implements Component {

  private String name;

  public Node(String name) { this.name = name; }

  public String toString() { return name; }

  public void operation() {

    System.out.println(this);

    for(Iterator it = iterator(); it.hasNext(); )

      ((Component)it.next()).operation();

  }

}

 

public class CompositeStructure extends TestCase {

  public void test() {

    Node root = new Node("root");

    root.add(new Leaf("Leaf1"));

    Node c2 = new Node("Node1");

    c2.add(new Leaf("Leaf2"));

    c2.add(new Leaf("Leaf3"));

    root.add(c2);

    c2 = new Node("Node2");

    c2.add(new Leaf("Leaf4"));

    c2.add(new Leaf("Leaf5"));

    root.add(c2);

    root.operation();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(CompositeStructure.class);

  }

} ///:~

 

While this approach seems to be “the simplest thing that could possibly work,” it’s possible that in a larger system problems could arise. However, it’s probably best to start with the simplest approach and change it only if the situation demands.

System decoupling

Observer

#[BT_383]#Like the other forms of callback, this contains a hook point where you can change code. The difference is in the observer’s completely dynamic nature. It is often used for the specific case of changes based on other object’s change of state, but is also the basis of event management. Anytime you want to decouple the source of the call from the called code in a completely dynamic way.

#[BT_384]#The observer pattern solves a fairly common problem: What if a group of objects needs to update themselves when some object changes state? This can be seen in the “model-view” aspect of Smalltalk’s MVC (model-view-controller), or the almost-equivalent “Document-View Architecture.” Suppose that you have some data (the “document”) and more than one view, say a plot and a textual view. When you change the data, the two views must know to update themselves, and that’s what the observer facilitates. It’s a common enough problem that its solution has been made a part of the standard java.util library.

#[BT_385]#There are two types of objects used to implement the observer pattern in Java. The Observable class keeps track of everybody who wants to be informed when a change happens, whether the “state” has changed or not. When someone says “OK, everybody should check and potentially update themselves,” the Observable class performs this task by calling the notifyObservers( ) method for each one on the list. The notifyObservers( ) method is part of the base class Observable.

#[BT_386]#There are actually two “things that change” in the observer pattern: the quantity of observing objects and the way an update occurs. That is, the observer pattern allows you to modify both of these without affecting the surrounding code.

#[BT_387]#-------------

#[BT_388]#Observer is an “interface” class that only has one member function, update( ). This function is called by the object that’s being observed, when that object decides its time to update all its observers. The arguments are optional; you could have an update( ) with no arguments and that would still fit the observer pattern; however this is more general—it allows the observed object to pass the object that caused the update (since an Observer may be registered with more than one observed object) and any extra information if that’s helpful, rather than forcing the Observer object to hunt around to see who is updating and to fetch any other information it needs.

#[BT_389]#The “observed object” that decides when and how to do the updating will be called the Observable.

#[BT_390]#Observable has a flag to indicate whether it’s been changed. In a simpler design, there would be no flag; if something happened, everyone would be notified. The flag allows you to wait, and only notify the Observers when you decide the time is right. Notice, however, that the control of the flag’s state is protected, so that only an inheritor can decide what constitutes a change, and not the end user of the resulting derived Observer class.

#[BT_391]#Most of the work is done in notifyObservers( ). If the changed flag has not been set, this does nothing. Otherwise, it first clears the changed flag so repeated calls to notifyObservers( ) won’t waste time. This is done before notifying the observers in case the calls to update( ) do anything that causes a change back to this Observable object. Then it moves through the set and calls back to the update( ) member function of each Observer.

#[BT_392]#At first it may appear that you can use an ordinary Observable object to manage the updates. But this doesn’t work; to get an effect, you must inherit from Observable and somewhere in your derived-class code call setChanged( ). This is the member function that sets the “changed” flag, which means that when you call notifyObservers( ) all of the observers will, in fact, get notified. Where you call setChanged( ) depends on the logic of your program.

Observing flowers

#[BT_393]#Here is an example of the observer pattern:

//: observer:ObservedFlower.java

// Demonstration of "observer" pattern.

package observer;

import java.util.*;

import junit.framework.*;

 

class Flower {

  private boolean isOpen;

  private OpenNotifier oNotify =

    new OpenNotifier();

  private CloseNotifier cNotify =

    new CloseNotifier();

  public Flower() { isOpen = false; }

  public void open() { // Opens its petals

    isOpen = true;

    oNotify.notifyObservers();

    cNotify.open();

  }

  public void close() { // Closes its petals

    isOpen = false;

    cNotify.notifyObservers();

    oNotify.close();

  }

  public Observable opening() { return oNotify; }

  public Observable closing() { return cNotify; }

  private class OpenNotifier extends Observable {

    private boolean alreadyOpen = false;

    public void notifyObservers() {

      if(isOpen && !alreadyOpen) {

        setChanged();

        super.notifyObservers();

        alreadyOpen = true;

      }

    }

    public void close() { alreadyOpen = false; }

  }

  private class CloseNotifier extends Observable{

    private boolean alreadyClosed = false;

    public void notifyObservers() {

      if(!isOpen && !alreadyClosed) {

        setChanged();

        super.notifyObservers();

        alreadyClosed = true;

      }

    }

    public void open() { alreadyClosed = false; }

  }

}

 

class Bee {

  private String name;

  private OpenObserver openObsrv =

    new OpenObserver();

  private CloseObserver closeObsrv =

    new CloseObserver();

  public Bee(String nm)  { name = nm; }

  // An inner class for observing openings:

  private class OpenObserver implements Observer{

    public void update(Observable ob, Object a) {

      System.out.println("Bee " + name

        + "'s breakfast time!");

    }

  }

  // Another inner class for closings:

  private class CloseObserver implements Observer{

    public void update(Observable ob, Object a) {

      System.out.println("Bee " + name

        + "'s bed time!");

    }

  }

  public Observer openObserver() {

    return openObsrv;

  }

  public Observer closeObserver() {

    return closeObsrv;

  }

}

 

class Hummingbird {

  private String name;

  private OpenObserver openObsrv =

    new OpenObserver();

  private CloseObserver closeObsrv =

    new CloseObserver();

  public Hummingbird(String nm) { name = nm; }

  private class OpenObserver implements Observer{

    public void update(Observable ob, Object a) {

      System.out.println("Hummingbird " + name

        + "'s breakfast time!");

    }

  }

  private class CloseObserver implements Observer{

    public void update(Observable ob, Object a) {

      System.out.println("Hummingbird " + name

        + "'s bed time!");

    }

  }

  public Observer openObserver() {

    return openObsrv;

  }

  public Observer closeObserver() {

    return closeObsrv;

  }

}

 

public class ObservedFlower extends TestCase {

  Flower f = new Flower();

  Bee

    ba = new Bee("A"),

    bb = new Bee("B");

  Hummingbird

    ha = new Hummingbird("A"),

    hb = new Hummingbird("B");

  public void test() {

    f.opening().addObserver(ha.openObserver());

    f.opening().addObserver(hb.openObserver());

    f.opening().addObserver(ba.openObserver());

    f.opening().addObserver(bb.openObserver());

    f.closing().addObserver(ha.closeObserver());

    f.closing().addObserver(hb.closeObserver());

    f.closing().addObserver(ba.closeObserver());

    f.closing().addObserver(bb.closeObserver());

    // Hummingbird B decides to sleep in:

    f.opening().deleteObserver(

      hb.openObserver());

    // A change that interests observers:

    f.open();

    f.open(); // It's already open, no change.

    // Bee A doesn't want to go to bed:

    f.closing().deleteObserver(

      ba.closeObserver());

    f.close();

    f.close(); // It's already closed; no change

    f.opening().deleteObservers();

    f.open();

    f.close();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(ObservedFlower.class);

  }

} ///:~

 

#[BT_394]#

#[BT_395]#The events of interest are that a Flower can open or close. Because of the use of the inner class idiom, both these events can be separately observable phenomena. OpenNotifier and CloseNotifier both inherit Observable, so they have access to setChanged( ) and can be handed to anything that needs an Observable.

#[BT_396]#The inner class idiom also comes in handy to define more than one kind of Observer, in Bee and Hummingbird, since both those classes may want to independently observe Flower openings and closings. Notice how the inner class idiom provides something that has most of the benefits of inheritance (the ability to access the private data in the outer class, for example) without the same restrictions.

#[BT_397]#In main( ), you can see one of the prime benefits of the observer pattern: the ability to change behavior at run time by dynamically registering and un-registering Observers with Observables.

#[BT_398]#If you study the code above you’ll see that OpenNotifier and CloseNotifier use the basic Observable interface. This means that you could inherit other completely different Observer classes; the only connection the Observers have with Flowers is the Observer interface.

A visual example of observers

#[BT_399]#The following example is similar to the ColorBoxes example from Chapter 14 in Thinking in Java, 2nd Edition. Boxes are placed in a grid on the screen and each one is initialized to a random color. In addition, each box implements the Observer interface and is registered with an Observable object. When you click on a box, all of the other boxes are notified that a change has been made because the Observable object automatically calls each Observer object’s update( ) method. Inside this method, the box checks to see if it’s adjacent to the one that was clicked, and if so it changes its color to match the clicked box.

//: observer:BoxObserver.java

// Demonstration of Observer pattern using

// Java's built-in observer classes.

package observer;

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.util.*;

 

// You must inherit a new type of Observable:

class BoxObservable extends Observable {

  public void notifyObservers(Object b) {

    // Otherwise it won't propagate changes:

    setChanged();

    super.notifyObservers(b);

  }

}

 

public class BoxObserver extends JFrame {

  Observable notifier = new BoxObservable();

  public BoxObserver(int grid) {

    setTitle("Demonstrates Observer pattern");

    Container cp = getContentPane();

    cp.setLayout(new GridLayout(grid, grid));

    for(int x = 0; x < grid; x++)

      for(int y = 0; y < grid; y++)

        cp.add(new OCBox(x, y, notifier));

  }  

  public static void main(String[] args) {

    int grid = 8;

    if(args.length > 0)

      grid = Integer.parseInt(args[0]);

    JFrame f = new BoxObserver(grid);

    f.setSize(500, 400);

    f.setVisible(true);

    f.setDefaultCloseOperation(EXIT_ON_CLOSE);

  }

}

 

class OCBox extends JPanel implements Observer {

  Observable notifier;

  int x, y; // Locations in grid

  Color cColor = newColor();

  static final Color[] colors = {

    Color.BLACK, Color.BLUE, Color.CYAN,

    Color.DARK_GRAY, Color.GRAY, Color.GREEN,

    Color.LIGHT_GRAY, Color.MAGENTA,

    Color.ORANGE, Color.PINK, Color.RED,

    Color.WHITE, Color.YELLOW

  };

  static Random rand = new Random();

  static final Color newColor() {

    return colors[rand.nextInt(colors.length)];

  }

  OCBox(int x, int y, Observable notifier) {

    this.x = x;

    this.y = y;

    notifier.addObserver(this);

    this.notifier = notifier;

    addMouseListener(new ML());

  }

  public void paintComponent(Graphics g) {

    super.paintComponent(g);

    g.setColor(cColor);

    Dimension s = getSize();

    g.fillRect(0, 0, s.width, s.height);

  }

  class ML extends MouseAdapter {

    public void mousePressed(MouseEvent e) {

      notifier.notifyObservers(OCBox.this);

    }

  }

  public void update(Observable o, Object arg) {

    OCBox clicked = (OCBox)arg;

    if(nextTo(clicked)) {

      cColor = clicked.cColor;

      repaint();

    }

  }

  private final boolean nextTo(OCBox b) {

    return Math.abs(x - b.x) <= 1 &&

           Math.abs(y - b.y) <= 1;

  }

} ///:~

 

#[BT_400]#When you first look at the online documentation for Observable, it’s a bit confusing because it appears that you can use an ordinary Observable object to manage the updates. But this doesn’t work; try it—inside BoxObserver, create an Observable object instead of a BoxObservable object and see what happens: nothing. To get an effect, you must inherit from Observable and somewhere in your derived-class code call setChanged( ). This is the method that sets the “changed” flag, which means that when you call notifyObservers( ) all of the observers will, in fact, get notified. In the example above setChanged( ) is simply called within notifyObservers( ), but you could use any criterion you want to decide when to call setChanged( ).

#[BT_401]#BoxObserver contains a single Observable object called notifier, and every time an OCBox object is created, it is tied to notifier. In OCBox, whenever you click the mouse the notifyObservers( ) method is called, passing the clicked object in as an argument so that all the boxes receiving the message (in their update( ) method) know who was clicked and can decide whether to change themselves or not. Using a combination of code in notifyObservers( ) and update( ) you can work out some fairly complex schemes.

#[BT_402]#It might appear that the way the observers are notified must be frozen at compile time in the notifyObservers( ) method. However, if you look more closely at the code above you’ll see that the only place in BoxObserver or OCBox where you're aware that you’re working with a BoxObservable is at the point of creation of the Observable object—from then on everything uses the basic Observable interface. This means that you could inherit other Observable classes and swap them at run time if you want to change notification behavior then.

Mediator

Sweep coupling under the rug, how is this different from MVC?

MVC has distinct model and view; mediator could be anything. MVC a flavor of mediator

Exercises

             1.             Create a minimal Observer-Observable design in two classes. Just create the bare minimum in the two classes, then demonstrate your design by creating one Observable and many Observers, and cause the Observable to update the Observers.

             2.             Create a minimal Observer system using java.util.Timer inside your Observable, to generate events that are reported to the Observers. Create several different Observers using anonymous inner classes, register these with the Observable, and show that they are called when the Timer events occur.

             3.             Modify BoxObserver.java to turn it into a simple game. If any of the squares surrounding the one you clicked is part of a contiguous patch of the same color, then all the squares in that patch are changed to the color you clicked on. You can configure the game for competition between players or to keep track of the number of clicks that a single player uses to turn the field into a single color. You may also want to restrict a player's color to the first one that was chosen.

#[BT_403]#

#[BT_404]#


Reducing interface complexity

#[BT_239]#Sometimes the problem that you’re solving is as simple as “I don’t have the interface that I want.” Façade creates an interface to a set of classes, simply to provide a more comfortable way to deal with a library or bundle of resources.

Façade

#[BT_243]#A general principle that I apply when I’m casting about trying to mold requirements into a first-cut object is “If something is ugly, hide it inside an object.” This is basically what Façade accomplishes. If you have a rather confusing collection of classes and interactions that the client programmer doesn’t really need to see, then you can create an interface that is useful for the client programmer and that only presents what’s necessary.

#[BT_244]#Façade is often implemented as singleton abstract factory. Of course, you can easily get this effect by creating a class containing static factory methods:

//: facade:Facade.java

package facade;

import junit.framework.*;

 

class A { public A(int x) {} }

class B { public B(long x) {} }

class C { public C(double x) {} }

 

// Other classes that aren't exposed

// by the facade go here ...

 

public class Facade extends TestCase  {

  static A makeA(int x) { return new A(x); }

  static B makeB(long x) { return new B(x); }

  static C makeC(double x) { return new C(x); }

  public void test() {

    // The client programmer gets the objects

    // by calling the static methods:

    A a = Facade.makeA(1);

    B b = Facade.makeB(1);

    C c = Facade.makeC(1.0);

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(Facade.class);

  }

} ///:~

#[BT_245]#

#[BT_246]#The example given in Design Patterns is just a class that uses the other classes.

A tax adviser is a Façade between you and the tax code, and a mediator between you and the tax system.A A

Package as a variation of Façade

#[BT_247]#To me, the Façade has a rather “procedural” (non-object-oriented) feel to it: you are just calling some functions to give you objects. And how different is it, really, from Abstract Factory? The point of Façade is to hide part of a library of classes (and their interactions) from the client programmer, to make the interface to that group of classes more digestible and easier to understand.

#[BT_248]#However, this is precisely what the packaging features in Java accomplish: outside of the library, you can only create and use public classes; all the non-public classes are only accessible within the package. It’s as if Façade is a built-in feature of Java.

#[BT_249]#To be fair, Design Patterns is written primarily for a C++ audience. Although C++ has namespaces to prevent clashes of globals and class names, this does not provide the class hiding mechanism that you get with non-public classes in Java. The majority of the time I think that Java packages will solve the Façade problem.

Algorithmic partitioning

 

Command: choosing the operation at run-time

#[BT_223]#In Advanced C++:Programming Styles And Idioms (Addison-Wesley, 1992), Jim Coplien coins the term functor which is an object whose sole purpose is to encapsulate a function (since “functor” has a meaning in mathematics, in this book I shall use the more explicit term function object). The point is to decouple the choice of function to be called from the site where that function is called.

#[BT_224]#This term is mentioned but not used in Design Patterns. However, the theme of the function object is repeated in a number of patterns in that book.

A Command is a function object in its purest sense: a method that’s an object[7]. By wrapping a method in an object, you can pass it to other methods or objects as a parameter, to tell them to perform this particular operation in the process of fulfilling your request. You could say that a Command is a messenger (because its intent and use is very straightforward) that carries behavior, rather than data.

//: command:CommandPattern.java

package command;

import java.util.*;

import junit.framework.*;

 

interface Command {

  void execute();

}

 

class Hello implements Command {

  public void execute() {

    System.out.print("Hello ");

  }

}

 

class World implements Command {

  public void execute() {

    System.out.print("World! ");

  }

}

 

class IAm implements Command {

  public void execute() {

    System.out.print("I'm the command pattern!");

  }

}

 

// An object that holds commands:

class Macro {

  private List commands = new ArrayList();

  public void add(Command c) { commands.add(c); }

  public void run() {

    Iterator it = commands.iterator();

    while(it.hasNext())

      ((Command)it.next()).execute();

  }

}

 

public class CommandPattern extends TestCase  {

  Macro macro = new Macro();

  public void test() {

    macro.add(new Hello());

    macro.add(new World());

    macro.add(new IAm());

    macro.run();

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(CommandPattern.class);

  }

} ///:~

#[BT_226]#

#[BT_227]#The primary point of Command is to allow you to hand a desired action to a method or object. In the above example, this provides a way to queue a set of actions to be performed collectively. In this case, it allows you to dynamically create new behavior, something you can normally only do by writing new code but in the above example could be done by interpreting a script (see the Interpreter pattern if what you need to do gets very complex).

#[BT_228]#Another example of Command is refactor:DirList.java [????]. The DirFilter class is the command object which contains its action in the method accept( ) that is passed to the list( ) method. The list( ) method determines what to include in its result by calling accept( ).

#[BT_229]#Design Patterns says that “Commands are an object-oriented replacement for callbacks[8].” However, I think that the word “back” is an essential part of the concept of callbacks. That is, I think a callback actually reaches back to the creator of the callback. On the other hand, with a Command object you typically just create it and hand it to some method or object, and are not otherwise connected over time to the Command object. That’s my take on it, anyway. Later in this book, I combine a group of design patterns under the heading of “callbacks.”

#[BT_230]#Strategy appears to be a family of Command classes, all inherited from the same base. But if you look at Command, you’ll see that it has the same structure: a hierarchy of function objects. The difference is in the way this hierarchy is used. As seen in refactor:DirList.java, you use Command to solve a particular problem—in that case, selecting files from a list. The “thing that stays the same” is the body of the method that’s being called, and the part that varies is isolated in the function object. I would hazard to say that Command provides flexibility while you’re writing the program, whereas Strategy’s flexibility is at run time. Nonetheless, it seems a rather fragile distinction.

Exercises

             4.             Use Command in Chapter 3, Exercise 1.

Chain of responsibility

Example: translation service (local->global->Babelfish).

#[BT_234]#Chain of Responsibility might be thought of as a dynamic generalization of recursion using Strategy objects. You make a call, and each Strategy in a linked sequence tries to satisfy the call. The process ends when one of the strategies is successful or the chain ends. In recursion, one method calls itself over and over until a termination condition is reached; with Chain of Responsibility, a method calls itself, which (by moving down the chain of Strategies) calls a different implementation of the method, etc., until a termination condition is reached. The termination condition is either the bottom of the chain is reached (in which case a default object is returned; you may or may not be able to provide a default result so you must be able to determine the success or failure of the chain) or one of the Strategies is successful.

#[BT_235]#Instead of calling a single method to satisfy a request, multiple methods in the chain have a chance to satisfy the request, so it has the flavor of an expert system. Since the chain is effectively a linked list, it can be dynamically created, so you could also think of it as a more general, dynamically-built switch statement.

In the GoF, there’s a fair amount of Thidiscussion of how to create the chain of responsibility as a linked list. However, when you look at the pattern it really shouldn’t matter how the chain is maintained; that’s an implementation detail. Since GoF was written before the Standard Template Library (STL) was incorporated into most C++ compilers, the reason for this is most likely (1) there was no list and thus they had to create one and (2) data structures are often taught as a fundamental skill in academia, and the idea that data structures should be standard tools available with the programming language may not have occurred to the GoF authors. I maintain that the implementation of Chain of Responsibility as a chain (specifically, a linked list) adds nothing to the solution and can just as easily be implemented using a standard Java List, as shown below. Furthermore, you’ll see that I’ve gone to some effort to separate the chain-management parts of the implementation from the various Strategies, so that the code can be more easily reused.

#[BT_236]#In StrategyPattern.java, above, what you probably want is to automatically find a solution. Chain of Responsibility provides a way to do this by chaining the Strategy objects together and providing a mechanism for them to automatically recurse through each one in the chain:

//: chainofresponsibility:FindMinima.java

package chainofresponsibility;

import com.bruceeckel.util.*; // Arrays2.toString()

import junit.framework.*;

 

// Carries the result data and

// whether the strategy was successful:

class LineData {

  public double[] data;

  public LineData(double[] data) { this.data = data; }

  private boolean succeeded;

  public boolean isSuccessful() { return succeeded; }

  public void setSuccessful(boolean b) { succeeded = b; }

}

 

interface Strategy {

  LineData strategy(LineData m);

}

 

class LeastSquares implements Strategy {

  public LineData strategy(LineData m) {

    System.out.println("Trying LeastSquares algorithm");

    LineData ld = (LineData)m;

    // [ Actual test/calculation here ]

    LineData r = new LineData(

      new double[] { 1.1, 2.2 }); // Dummy data

    r.setSuccessful(false);

    return r;

  }

}

 

class NewtonsMethod implements Strategy {

  public LineData strategy(LineData m) {

    System.out.println("Trying NewtonsMethod algorithm");

    LineData ld = (LineData)m;

    // [ Actual test/calculation here ]

    LineData r = new LineData(

      new double[] { 3.3, 4.4 }); // Dummy data

    r.setSuccessful(false);

    return r;

  }

}

 

class Bisection implements Strategy {

  public LineData strategy(LineData m) {

    System.out.println("Trying Bisection algorithm");

    LineData ld = (LineData)m;

    // [ Actual test/calculation here ]

    LineData r = new LineData(

      new double[] { 5.5, 6.6 }); // Dummy data

    r.setSuccessful(true);

    return r;

  }

}

 

class ConjugateGradient implements Strategy {

  public LineData strategy(LineData m) {

    System.out.println(

      "Trying ConjugateGradient algorithm");

    LineData ld = (LineData)m;

    // [ Actual test/calculation here ]

    LineData r = new LineData(

      new double[] { 5.5, 6.6 }); // Dummy data

    r.setSuccessful(true);

    return r;

  }

}

 

class MinimaFinder {

  private static Strategy[] solutions = {

    new LeastSquares(),

    new NewtonsMethod(),

    new Bisection(),

    new ConjugateGradient(),

  };

  public static LineData solve(LineData line) {

    LineData r = line;

    for(int i = 0; i < solutions.length; i++) {

      r = solutions[i].strategy(r);

      if(r.isSuccessful())

        return r;

    }

    throw new RuntimeException("unsolved: " + line);

  }

}

 

public class FindMinima extends TestCase  {

  LineData line = new LineData(new double[]{

    1.0, 2.0, 1.0, 2.0, -1.0, 3.0, 4.0, 5.0, 4.0

  });

  public void test() {

    System.out.println(Arrays2.toString(

      ((LineData)MinimaFinder.solve(line)).data));

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(FindMinima.class);

  }

} ///:~

 

Exercises

             1.             Implement Chain of Responsibility to create an "expert system" that solves problems by successively trying one solution after another until one matches. You should be able to dynamically add solutions to the expert system. The test for solution should just be a string match, but when a solution fits, the expert system should return the appropriate type of ProblemSolver object. What other pattern/patterns show up here?

             2.             Implement Chain of Responsibility to create a language translator which begins by searching for a local specialized translation system (which may know specifics about your problem domain), then a more global generalized system, and finally falls back on BabelFish if it can’t translate everything. Note that each link in the chain may partially translate what it’s able to.

             3.             Implement Chain of Responsibility to create an tool to help reformat Java source code by trying multiple approaches to breaking lines. Note that normal code and comments will probably need to be treated differently, leading to the possibility of implementing a Tree of Responsibility. Also note the similarity between this approach and the Composite design pattern; perhaps the more general description of this technique is a Composite of Strategies.

#[BT_238]#


Externalizing object state

Memento

Use serialization to create an undo mechanism.

Complex interactions

Multiple dispatching

#[BT_405]#When dealing with multiple types which are interacting, a program can get particularly messy. For example, consider a system that parses and executes mathematical expressions. You want to be able to say Number + Number, Number * Number, etc., where Number is the base class for a family of numerical objects. But when you say a + b, and you don’t know the exact type of either a or b, so how can you get them to interact properly?

#[BT_406]#The answer starts with something you probably don’t think about: Java performs only single dispatching. That is, if you are performing an operation on more than one object whose type is unknown, Java can invoke the dynamic binding mechanism on only one of those types. This doesn’t solve the problem, so you end up detecting some types manually and effectively producing your own dynamic binding behavior.

#[BT_407]#The solution is called multiple dispatching. Remember that polymorphism can occur only via member function calls, so if you want double dispatching to occur, there must be two member function calls: the first to determine the first unknown type, and the second to determine the second unknown type. With multiple dispatching, you must have a polymorphic method call to determine each of the types. Generally, you’ll set up a configuration such that a single member function call produces more than one dynamic member function call and thus determines more than one type in the process. To get this effect, you need to work with more than one polymorphic method call: you’ll need one call for each dispatch. The methods in the following example are called compete( ) and eval( ), and are both members of the same type. (In this case there will be only two dispatches, which is referred to as double dispatching). If you are working with two different type hierarchies that are interacting, then you’ll have to have a polymorphic method call in each hierarchy.

#[BT_408]#Here’s an example of multiple dispatching:

//: multipledispatch:PaperScissorsRock.java

// Demonstration of multiple dispatching.

package multipledispatch;

import java.util.*;

import junit.framework.*;

 

// An enumeration type:

class Outcome {

  private String name;

  private Outcome(String name) { this.name = name; }

  public final static Outcome

    WIN = new Outcome("wins"),

    LOSE = new Outcome("loses"),

    DRAW = new Outcome("draws");

  public String toString() { return name; }

}

 

interface Item {

  Outcome compete(Item it);

  Outcome eval(Paper p);

  Outcome eval(Scissors s);

  Outcome eval(Rock r);

}

 

class Paper implements Item {

  public Outcome compete(Item it) { return it.eval(this); }

  public Outcome eval(Paper p) { return Outcome.DRAW; }

  public Outcome eval(Scissors s) { return Outcome.WIN; }

  public Outcome eval(Rock r) { return Outcome.LOSE; }

  public String toString() { return "Paper"; }

}

 

class Scissors implements Item {

  public Outcome compete(Item it) { return it.eval(this); }

  public Outcome eval(Paper p) { return Outcome.LOSE; }

  public Outcome eval(Scissors s) { return Outcome.DRAW; }

  public Outcome eval(Rock r) { return Outcome.WIN; }

  public String toString() { return "Scissors"; }

}

 

class Rock implements Item {

  public Outcome compete(Item it) { return it.eval(this); }

  public Outcome eval(Paper p) { return Outcome.WIN; }

  public Outcome eval(Scissors s) { return Outcome.LOSE; }

  public Outcome eval(Rock r) { return Outcome.DRAW; }

  public String toString() { return "Rock"; }

}

 

class ItemGenerator {

  private static Random rand = new Random();

  public static Item newItem() {

    switch(rand.nextInt(3)) {

      default:

      case 0: return new Scissors();

      case 1: return new Paper();

      case 2: return new Rock();

    }

  }

}

 

class Compete {

  public static void match(Item a, Item b) {

    System.out.println(

      a + " " + a.compete(b) + " vs. " + b);

  }

}

 

public class PaperScissorsRock extends TestCase  {

  static int SIZE = 20;

  public void test() {

    for(int i = 0; i < SIZE; i++)

      Compete.match(ItemGenerator.newItem(),

        ItemGenerator.newItem());

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(PaperScissorsRock.class);

  }

} ///:~

 

 

 

#[BT_409]#

#[BT_410]#

Visitor, a type of multiple dispatching

#[BT_411]#The assumption is that you have a primary class hierarchy that is fixed; perhaps it’s from another vendor and you can’t make changes to that hierarchy. However, you’d like to add new polymorphic methods to that hierarchy, which means that normally you’d have to add something to the base class interface. So the dilemma is that you need to add methods to the base class, but you can’t touch the base class. How do you get around this?

#[BT_412]#The design pattern that solves this kind of problem is called a “visitor” (the final one in the Design Patterns book), and it builds on the double dispatching scheme shown in the last section.

#[BT_413]#The visitor pattern allows you to extend the interface of the primary type by creating a separate class hierarchy of type Visitor to virtualize the operations performed upon the primary type. The objects of the primary type simply “accept” the visitor, then call the visitor’s dynamically-bound member function.

//: visitor:BeeAndFlowers.java

// Demonstration of "visitor" pattern.

package visitor;

import java.util.*;

import junit.framework.*;

 

interface Visitor { 

  void visit(Gladiolus g);

  void visit(Runuculus r);

  void visit(Chrysanthemum c);

}

 

// The Flower hierarchy cannot be changed:

interface Flower { 

  void accept(Visitor v);

}

 

class Gladiolus implements Flower { 

  public void accept(Visitor v) { v.visit(this);}

}

 

class Runuculus implements Flower { 

  public void accept(Visitor v) { v.visit(this);}

}

 

class Chrysanthemum implements Flower { 

  public void accept(Visitor v) { v.visit(this);}

}

 

// Add the ability to produce a string:

class StringVal implements Visitor {

  String s; 

  public String toString() { return s; }

  public void visit(Gladiolus g) {

    s = "Gladiolus";

  }

  public void visit(Runuculus r) {

    s = "Runuculus";

  }

  public void visit(Chrysanthemum c) {

    s = "Chrysanthemum";

  }

}

 

// Add the ability to do "Bee" activities:

class Bee implements Visitor { 

  public void visit(Gladiolus g) {

    System.out.println("Bee and Gladiolus");

  }

  public void visit(Runuculus r) {

    System.out.println("Bee and Runuculus");

  }

  public void visit(Chrysanthemum c) {

    System.out.println("Bee and Chrysanthemum");

  }

}

 

class FlowerGenerator {

  private static Random rand = new Random();

  public static Flower newFlower() {

    switch(rand.nextInt(3)) {

      default:

      case 0: return new Gladiolus();

      case 1: return new Runuculus();

      case 2: return new Chrysanthemum();

    }

  }

}

 

public class BeeAndFlowers extends TestCase  {

  List flowers = new ArrayList();

  public BeeAndFlowers() {

    for(int i = 0; i < 10; i++)

      flowers.add(FlowerGenerator.newFlower());

  }

  public void test() {

    // It's almost as if I had a function to

    // produce a Flower string representation:

    StringVal sval = new StringVal();

    Iterator it = flowers.iterator();

    while(it.hasNext()) {

      ((Flower)it.next()).accept(sval);

      System.out.println(sval);

    }

    // Perform "Bee" operation on all Flowers:

    Bee bee = new Bee();

    it = flowers.iterator();

    while(it.hasNext())

      ((Flower)it.next()).accept(bee);

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(BeeAndFlowers.class);

  }

} ///:~

#[BT_414]#

Exercises

             1.             Create a business-modeling environment with three types of Inhabitant: Dwarf (for engineers), Elf (for marketers) and Troll (for managers). Now create a class called Project that creates the different inhabitants and causes them to interact( ) with each other using multiple dispatching.

             2.             Modify the above example to make the interactions more detailed. Each Inhabitant can randomly produce a Weapon using getWeapon( ): a Dwarf uses Jargon or Play, an Elf uses InventFeature or SellImaginaryProduct, and a Troll uses Edict and Schedule. You must decide which weapons “win” and “lose” in each interaction (as in PaperScissorsRock.java). Add a battle( ) member function to Project that takes two Inhabitants and matches them against each other. Now create a meeting( ) member function for Project that creates groups of Dwarf, Elf and Manager and battles the groups against each other until only members of one group are left standing. These are the “winners.”

             3.             Modify PaperScissorsRock.java to replace the double dispatching with a table lookup. The easiest way to do this is to create a Map of Maps, with the key of each Map the class of each object. Then you can do the lookup by saying:
((Map)map.get(o1.getClass())).get(o2.getClass())
Notice how much easier it is to reconfigure the system. When is it more appropriate to use this approach vs. hard-coding the dynamic dispatches? Can you create a system that has the syntactic simplicity of use of the dynamic dispatch but uses a table lookup?

             4.             Modify Exercise 2 to use the table lookup technique described in Exercise 3.

#[BT_415]#

#[BT_416]#


Multiple languages

#[BT_256]#This chapter looks at the value of crossing language boundaries. It is often very advantageous to solve a problem using more than one programming language, rather than being arbitrarily stuck using a single language. As you’ll see in this chapter, a problem that is very difficult or tedious to solve in one language can often be solved quickly and easily in another. If you can combine the use of languages, you can create your product much more quickly and cheaply.

#[BT_257]#The most straightforward use of this idea is the Interpreter design pattern, which adds an interpreted language to your program to allow the end user to easily customize a solution. In Java, the easiest and most powerful way to do this is with Jython[9], an implementation of the Python language in pure Java byte codes.

#[BT_258]#Interpreter solves a particular problem – that of creating a scripting language for the user. But sometimes it’s just easier and faster to temporarily step into another language to solve a particular aspect of your problem. You’re not creating an interpreter, you’re just writing some code in another language. Again, Jython is a good example of this, but CORBA also allows you to cross language boundaries.

Interpreter motivation

#[BT_259]#If the application user needs greater run time flexibility, for example to create scripts describing the desired behavior of the system, you can use the Interpreter design pattern. Here, you create and embed a language interpreter into your program.

#[BT_260]#Remember that each design pattern allows one or more factors to change, so it’s important to first be aware of which factor is changing. Sometimes the end users of your application (rather than the programmers of that application) need complete flexibility in the way that they configure some aspect of the program. That is, they need to do some kind of simple programming. The interpreter pattern provides this flexibility by adding a language interpreter.

#[BT_261]#The problem is that developing your own language and building an interpreter is a time-consuming distraction from the process of developing your application. You must ask whether you want to finish writing your application or create a new language.  The best solution is to reuse code: embed an interpreter that’s already been built and debugged for you. The Python language can be freely embedded into your for-profit application without signing any license agreement, paying royalties, or dealing with strings of any kind. There are basically no restrictions at all when you're using Python.

#[BT_262]#Python is a language that is very easy to learn, very logical to read and write, supports functions and objects, has a large set of available libraries, and runs on virtually every platform. You can download Python and learn more about it by going to www.Python.org.

#[BT_263]#For solving Java problems, we will look at a special version of Python called Jython. This is generated entirely in Java byte codes, so incorporating it into your application is quite simple,  and it’s as portable as Java is. It has an extremely clean interface with Java: Java can call Python classes, and Python can call Java classes.

#[BT_264]#Python is designed with classes from the ground up and is a truly pure object oriented language (both C++ and Java violate purity in various ways). Python scales up so that you can create very big programs without losing control of the code.

#[BT_265]#To install Python, go to www.Python.org and follow the links and instructions. To install Jython, go to http://jython.sourceforge.net.  The download is a .class file, which will run an installer when you execute it with Java.  You also need to add jython.jar to your CLASSPATH. You can find further installation instructions at http://www.bruceeckel.com/TIPatterns/Building-Code.html.

Python overview

#[BT_266]#To get you started, here is a brief introduction for the experienced programmer (which is what you should be if you’re reading this book). You can refer to the full documentation at www.Python.org (especially the incredibly useful HTML page A Python Quick Reference), and also numerous books such as Learning Python by Mark Lutz and David Ascher (O’Reilly, 1999).

#[BT_267]#Python is often referred to as a scripting language, but scripting languages tend to be limiting, especially in the scope of the problems that they solve. Python, on the other hand, is a programming language that also supports scripting. It is marvelous for scripting, and you may find yourself replacing all your batch files, shell scripts, and simple programs with Python scripts. But it is far more than a scripting language.

#[BT_268]#Python is designed to be very clean to write and especially to read. You will find that it’s quite easy to read your own code long after you’ve written it, and also to read other people’s code. This is accomplished partially through clean, to-the-point syntax, but a major factor in code readability is indentation – scoping in Python is determined by indentation. For example:

##interpreter:if.py

response = "yes"

if response == "yes":

  print "affirmative"

  val = 1

print "continuing..."

##~

#[BT_269]#The ‘#’ denotes a comment that goes until the end of the line, just like C++ and Java ‘//’ comments.

#[BT_270]#First notice that the basic syntax of Python is C-ish; notice the if statement. But in a C if, you would be required to use parentheses around the conditional, whereas they are not necessary in Python (but it won’t complain if you use them anyway).

#[BT_271]#The conditional clause ends with a colon, and this indicates that what follows will be a group of indented statements, which are the “then” part of the if statement. In this case, there is a “print” statement which sends the result to standard output, followed by an assignment to a variable named val. The subsequent statement is not indented so it is no longer part of the if. Indenting can nest to any level, just like curly braces in C++ or Java, but unlike those languages there is no option (and no argument) about where the braces are placed – the compiler forces everyone’s code to be formatted the same way, which is one of the main reasons for Python’s consistent readability.

#[BT_272]#Python normally has only one statement per line (you can put more by separating them with semicolons), thus no terminating semicolon is necessary.  Even from the brief example above you can see that the language is designed to be as simple as possible, and yet still very readable.

Built-in containers

#[BT_273]#With languages like C++ and Java, containers are add-on libraries and not integral to the language. In Python, the essential nature of containers for programming is acknowledged by building them into the core of the language: both lists and associative arrays (a.k.a. maps, dictionaries, hash tables) are fundamental data types. This adds much to the elegance of the language.

#[BT_274]#In addition, the for statement automatically iterates through lists rather than just counting through a sequence of numbers. This makes a lot of sense when you think about it, since you’re almost always using a for loop to step through an array or a container. Python formalizes this by automatically making for use an iterator that works through a sequence. Here’s an example:

## interpreter:list.py

list = [ 1, 3, 5, 7, 9, 11 ]

print list

list.append(13)

for x in list:

  print x

##~

#[BT_275]#The first line creates a list. You can print the list and it will look exactly as you put it in (in contrast, remember that I had to create a special Arrays2 class in Thinking in Java, 2nd Edition in order to print arrays in Java). Lists are like Java containers – you can add new elements to them (here, append( ) is used) and they will automatically resize themselves. The for statement creates an iterator x which takes on each value in the list.

#[BT_276]#You can create a list of numbers with the range( ) function, so if you really need to imitate C’s for, you can.

#[BT_277]#Notice that there aren’t any type declarations – the object names simply appear, and Python infers their type by the way that you use them. It’s as if Python is designed so that you only need to press the keys that absolutely must. You’ll find after you’ve worked with Python for a short while that you’ve been using up a lot of brain cycles parsing semicolons, curly braces, and all sorts of other extra verbiage that was demanded by your non-Python programming language but didn’t actually describe what your program was supposed to do.

Functions

#[BT_278]#To create a function in Python, you use the def keyword, followed by the function name and argument list, and a colon to begin the function body. Here is the first example turned into a function:

## interpreter:myFunction.py

def myFunction(response):

  val = 0

  if response == "yes":

    print "affirmative"

    val = 1

  print "continuing..."

  return val

 

print myFunction("no")

print myFunction("yes")

##~

#[BT_279]#Notice there is no type information in the function signature – all it specifies is the name of the function and the argument identifiers, but no argument types or return types. Python is a weakly-typed language, which means it puts the minimum possible requirements on typing. For example, you could pass and return different types from the same function:

## interpreter:differentReturns.py

def differentReturns(arg):

  if arg == 1:

    return "one"

  if arg == "one":

    return 1

 

print differentReturns(1)

print differentReturns("one")

##~

#[BT_280]#The only constraints on an object that is passed into the function are that the function can apply its operations to that object, but other than that, it doesn’t care. Here, the same function applies the ‘+’ operator to integers and strings:

## interpreter:sum.py

def sum(arg1, arg2):

  return arg1 + arg2

 

print sum(42, 47)

print sum('spam ', "eggs")

##~

#[BT_281]#When the operator ‘+’ is used with strings, it means concatenation (yes, Python supports operator overloading, and it does a nice job of it).

Strings

#[BT_282]#The above example also shows a little bit about Python string handling,  which is the best of any language I’ve seen. You can use single or double quotes to represent strings, which is very nice because if you surround a string with double quotes, you can embed single quotes and vice versa:

## interpreter:strings.py

print "That isn't a horse"

print 'You are not a "Viking"'

print """You're just pounding two

coconut halves together."""

print '''"Oh no!" He exclaimed.

"It's the blemange!"'''

print r'c:\python\lib\utils'

##~

#[BT_283]#Note that Python was not named after the snake, but rather the Monty Python comedy troupe, and so examples are virtually required to include Python-esque references.

#[BT_284]#The triple-quote syntax quotes everything, including newlines. This makes it particularly useful for doing things like generating web pages (Python is an especially good CGI language), since you can just triple-quote the entire page that you want without any other editing.

#[BT_285]#The ‘r’ right before a string means “raw,” which takes the backslashes literally so you don’t have to put in an extra backslash.

#[BT_286]#Substitution in strings is exceptionally easy, since Python uses C’s printf( ) substitution syntax, but for any string at all. You simply follow the string with a ‘%’ and the values to substitute:

## interpreter:stringFormatting.py

val = 47

print "The number is %d" % val

val2 = 63.4

s = "val: %d, val2: %f" % (val, val2)

print s

##~

#[BT_287]#As you can see in the second case, if you have more than one argument you surround them in parentheses (this forms a tuple, which is a list that cannot be modified).

#[BT_288]#All the formatting from printf( ) is available, including control over the number of decimal places and alignment. Python also has very sophisticated regular expressions.

Classes

#[BT_289]#Like everything else in Python, the definition of a class uses a minimum of additional syntax. You use the class keyword, and inside the body you use def to create methods. Here’s a simple class:

## interpreter:SimpleClass.py

class Simple:

  def __init__(self, str):

    print "Inside the Simple constructor"

    self.s = str

  # Two methods:

  def show(self):

    print self.s

  def showMsg(self, msg):

    print msg + ':',

    self.show() # Calling another method

 

if __name__ == "__main__":

  # Create an object:

  x = Simple("constructor argument")

  x.show()

  x.showMsg("A message")

##~

#[BT_290]#Both methods have “self as their first argument. C++ and Java both have a hidden first argument in their class methods, which points to the object that the method was called for and can be accessed using the keyword this. Python methods also use a reference to the current object, but when you are defining a method you must explicitly specify the reference as the first argument. Traditionally, the reference is called self but you could use any identifier you want (if you do not use self you will probably confuse a lot of people, however). If you need to refer to fields in the object or other methods in the object, you must use self in the expression. However, when you call a method for an object as in x.show( ), you do not hand it the reference to the object – that is done for you.

#[BT_291]#Here, the first method is special, as is any identifier that begins and ends with double underscores. In this case, it defines the constructor, which is automatically called when the object is created, just like in C++ and Java. However, at the bottom of the example you can see that the creation of an object looks just like a function call using the class name. Python’s spare syntax makes you realize that the new keyword isn’t really necessary in C++ or Java, either.

#[BT_292]#All the code at the bottom is set off by an if clause, which checks to see if something called __name­__ is equivalent to __main__. Again, the double underscores indicate special names. The reason for the if is that any file can also be used as a library module within another program (modules are described shortly). In that case, you just want the classes defined, but you don’t want the code at the bottom of the file to be executed. This particular if statement is only true when you are running this file directly; that is, if you say on the command line:

Python SimpleClass.py

#[BT_293]#However, if this file is imported as a module into another program, the __main__ code is not executed.

#[BT_294]#Something that’s a little surprising at first is that you define fields inside methods, and not outside of the methods like C++ or Java (if you create fields using the C++/Java style, they implicitly become static fields). To create an object field, you just name it – using self – inside of one of the methods (usually in the constructor, but not always), and space is created when that method is run. This seems a little strange coming from C++ or Java where you must decide ahead of time how much space your object is going to occupy, but it turns out to be a very flexible way to program.

Inheritance

#[BT_295]#Because Python is weakly typed, it doesn’t really care about interfaces – all it cares about is applying operations to objects (in fact, Java’s interface keyword would be wasted in Python). This means that inheritance in Python is different from inheritance in C++ or Java, where you often inherit simply to establish a common interface. In Python, the only reason you inherit is to inherit an implementation – to re-use the code in the base class.

#[BT_296]#If you’re going to inherit from a class, you must tell Python to bring that class into your new file. Python controls its name spaces as aggressively as Java does, and in a similar fashion (albeit with Python’s penchant for simplicity). Every time you create a file, you implicitly create a module (which is like a package in Java) with the same name as that file. Thus, no package keyword is needed in Python. When you want to use a module, you just say import and give the name of the module. Python searches the PYTHONPATH in the same way that Java searches the CLASSPATH (but for some reason, Python doesn’t have the same kinds of pitfalls as Java does) and reads in the file. To refer to any of the functions or classes within a module, you give the module name, a period, and the function or class name. If you don’t want the trouble of qualifying the name, you can say

#[BT_297]#from module import name(s)

#[BT_298]#Where “name(s)” can be a list of names separated by commas.

#[BT_299]#You inherit a class (or classes – Python supports multiple inheritance) by listing the name(s) of the class inside parentheses after the name of the inheriting class. Note that the Simple class, which resides in the file (and thus, module) named SimpleClass is brought into this new name space using an import statement:

## interpreter:Simple2.py

from SimpleClass import Simple

 

class Simple2(Simple):

  def __init__(self, str):

    print "Inside Simple2 constructor"

    # You must explicitly call

    # the base-class constructor:

    Simple.__init__(self, str)

  def display(self):

    self.showMsg("Called from display()")

  # Overriding a base-class method

  def show(self):

    print "Overridden show() method"

    # Calling a base-class method from inside

    # the overridden method:

    Simple.show(self)

 

class Different:

  def show(self):

    print "Not derived from Simple"

 

if __name__ == "__main__":

  x = Simple2("Simple2 constructor argument")

  x.display()

  x.show()

  x.showMsg("Inside main")

  def f(obj): obj.show() # One-line definition

  f(x)

  f(Different())

##~

#[BT_300]#Simple2 is inherited from Simple, and in the constructor, the base-class constructor is called. In display( ), showMsg( ) can be called as a method of self, but when calling the base-class version of the method you are overriding, you must fully qualify the name and pass self in as the first argument, as shown in the base-class constructor call. This can also be seen in the overridden version of show( ).

#[BT_301]#In __main__, you will see (when you run the program) that the base-class constructor is called. You can also see that the showMsg( ) method is available in the derived class, just as you would expect with inheritance.

#[BT_302]#The class Different also has a method named show( ), but this class is not derived from Simple. The f( ) method defined in __main__ demonstrates weak typing: all it cares about is that show( ) can be applied to obj, and it doesn’t have any other type requirements. You can see that f( ) can be applied equally to an object of a class derived from Simple and one that isn’t, without discrimination. If you’re a C++ programmer, you should see that the objective of the C++ template feature is exactly this: to provide weak typing in a strongly-typed language. Thus, in Python you automatically get the equivalent of templates – without having to learn that particularly difficult syntax and semantics.

Creating a language

#[BT_303]#It turns out to be remarkably simple to use Jython to create an interpreted language inside your application. Consider the greenhouse controller example from Chapter 8 of Thinking in Java, 2nd edition. This is a situation where you want the end user – the person managing the greenhouse – to have configuration control over the system, and so a simple scripting language is the ideal solution.

#[BT_304]#To create the language, we’ll simply write a set of Python classes, and the constructor of each will add itself to a (static) master list. The common data and behavior will be factored into the base class Event. Each Event object will contain an action string (for simplicity – in reality, you’d have some sort of functionality) and a time when the event is supposed to run. The constructor initializes these fields, and then adds the new Event object to a static list called events (defining it in the class, but outside of any methods, is what makes it static):

#:interpreter:GreenHouseLanguage.py

 

class Event:

  events = [] # static

  def __init__(self, action, time):

    self.action = action

    self.time = time

    Event.events.append(self)

  # Used by sort(). This will cause

  # comparisons to be based only on time:

  def __cmp__ (self, other):

    if self.time < other.time: return -1

    if self.time > other.time: return 1

    return 0

  def run(self):

    print "%.2f: %s" % (self.time, self.action)

 

class LightOn(Event):

  def __init__(self, time):

    Event.__init__(self, "Light on", time)

 

class LightOff(Event):

  def __init__(self, time):

    Event.__init__(self, "Light off", time)

 

class WaterOn(Event):

  def __init__(self, time):

    Event.__init__(self, "Water on", time)

 

class WaterOff(Event):

  def __init__(self, time):

    Event.__init__(self, "Water off", time)

 

class ThermostatNight(Event):

  def __init__(self, time):

    Event.__init__(self,"Thermostat night", time)

 

class ThermostatDay(Event):

  def __init__(self, time):

    Event.__init__(self, "Thermostat day", time)

 

class Bell(Event):

  def __init__(self, time):

    Event.__init__(self, "Ring bell", time)

 

def run():

  Event.events.sort();

  for e in Event.events:

    e.run()

 

# To test, this will be run when you say:

# python GreenHouseLanguage.py

if __name__ == "__main__":

  ThermostatNight(5.00)

  LightOff(2.00)

  WaterOn(3.30)

  WaterOff(4.45)

  LightOn(1.00)

  ThermostatDay(6.00)

  Bell(7.00)

  run()

##~

#[BT_305]#The constructor of each derived class calls the base-class constructor, which adds the new object to the list. The run( ) function sorts the list, which automatically uses the __cmp__( ) method that was defined in Event to base comparisons on time only. In this example, it only prints out the list, but in the real system it would wait for the time of each event to come up and then run the event.

#[BT_306]#The __main__ section performs a simple test on the classes.

#[BT_307]#The above file is now a module that can be included in another Python program to define all the classes it contains. But instead of an ordinary Python program, let’s use Jython, inside of Java. This turns out to be remarkably simple: you import some Jython classes, create a PythonInterpreter object, and cause the Python files to be loaded:

//- interpreter:GreenHouseController.java

package interpreter;

import org.python.util.PythonInterpreter;

import org.python.core.*;

import junit.framework.*;

 

public class

GreenHouseController extends TestCase  {

  PythonInterpreter interp =

    new PythonInterpreter();

  public void test() throws PyException  {

    System.out.println(

      "Loading GreenHouse Language");

    interp.execfile("GreenHouseLanguage.py");

    System.out.println(

      "Loading GreenHouse Script");

    interp.execfile("Schedule.ghs");

    System.out.println(

      "Executing GreenHouse Script");

    interp.exec("run()");

  }

  public static void

  main(String[] args) throws PyException  {

    junit.textui.TestRunner.run(GreenHouseController.class);

  }

} ///:~

#[BT_308]#

#[BT_309]#The PythonInterpreter object is a complete Python interpreter that accepts commands from the Java program. One of these commands is execfile( ), which tells it to execute all the statements it finds in a particular file. By executing GreenHouseLanguage.py, all the classes from that file are loaded into our PythonInterpreter object, and so it now “holds” the greenhouse controller language. The Schedule.ghs file is the one created by the end user to control the greenhouse. Here’s an example:

//:! interpreter:Schedule.ghs

Bell(7.00)

ThermostatDay(6.00)

WaterOn(3.30)

LightOn(1.00)

ThermostatNight(5.00)

LightOff(2.00)

WaterOff(4.45)

///:~

#[BT_310]#

#[BT_311]#This is the goal of the interpreter design pattern: to make the configuration of your program as simple as possible for the end user. With Jython you can achieve this with almost no effort at all.

#[BT_312]#One of the other methods available to the PythonInterpreter is exec( ), which allows you to send a command to the interpreter. Here, the run( ) function is called using exec( ).

#[BT_313]#Remember, to run this program you must go to http://jython.sourceforge.net and download and install Jython (actually, you only need jython.jar in your CLASSPATH). Once that’s in place, it’s just like running any other Java program.

Controlling the interpreter

#[BT_314]#The prior example only creates and runs the interpreter using external scripts. In the rest of this chapter, we shall look at more sophisticated ways to interact with Jython. The simplest way to exercise more control over the PythonInterpreter object from within Java is to send data to the interpreter, and pull data back out.

Putting data in

#[BT_315]#To inject data into your Python program, the PythonInterpreter class has a deceptively simple method: set( ). However, set( ) takes many different data types and performs conversions upon them.  The following example is a reasonably thorough exercise of the various set( ) possibilities, along with comments that should give a fairly complete explanation:

//- interpreter:PythonInterpreterSetting.java

// Passing data from Java to python when using

// the PythonInterpreter object.

package interpreter;

import org.python.util.PythonInterpreter;

import org.python.core.*;

import java.util.*;

import com.bruceeckel.python.*;

import junit.framework.*;

 

public class

PythonInterpreterSetting extends TestCase  {

  PythonInterpreter interp =

    new PythonInterpreter();

  public void test() throws PyException  {

    // It automatically converts Strings

    // into native Python strings:

    interp.set("a", "This is a test");

    interp.exec("print a");

    interp.exec("print a[5:]"); // A slice

    // It also knows what to do with arrays:

    String[] s = { "How", "Do", "You", "Do?" };

    interp.set("b", s);

    interp.exec("for x in b: print x[0], x");

    // set() only takes Objects, so it can't

    // figure out primitives. Instead,

    // you have to use wrappers:

    interp.set("c", new PyInteger(1));

    interp.set("d", new PyFloat(2.2));

    interp.exec("print c + d");

    // You can also use Java's object wrappers:

    interp.set("c", new Integer(9));

    interp.set("d", new Float(3.14));

    interp.exec("print c + d");

    // Define a Python function to print arrays:

    interp.exec(

      "def prt(x): \n" +

      "  print x \n" +

      "  for i in x: \n" +

      "    print i, \n" +

      "  print x.__class__\n");

    // Arrays are Objects, so it has no trouble

    // figuring out the types contained in arrays:

    Object[] types = {

      new boolean[]{ true, false, false, true },

      new char[]{ 'a', 'b', 'c', 'd' },

      new byte[]{ 1, 2, 3, 4 },

      new int[]{ 10, 20, 30, 40 },

      new long[]{ 100, 200, 300, 400 },

      new float[]{ 1.1f, 2.2f, 3.3f, 4.4f },

      new double[]{ 1.1, 2.2, 3.3, 4.4 },

    };

    for(int i = 0; i < types.length; i++) {

      interp.set("e", types[i]);

      interp.exec("prt(e)");

    }

    // It uses toString() to print Java objects:

    interp.set("f", new Date());

    interp.exec("print f");

    // You can pass it a List

    // and index into it...

    List x = new ArrayList();

    for(int i = 0; i < 10; i++)

        x.add(new Integer(i * 10));

    interp.set("g", x);

    interp.exec("print g");

    interp.exec("print g[1]");

    // ... But it's not quite smart enough

    // to treat it as a Python array:

    interp.exec("print g.__class__");

    // interp.exec("print g[5:]); // Fails

    // If you want it to be a python array, you

    // must extract the Java array:

    System.out.println("ArrayList to array:");

    interp.set("h", x.toArray());

    interp.exec("print h.__class__");

    interp.exec("print h[5:]");

    // Passing in a Map:

    Map m = new HashMap();

    m.put(new Integer(1), new Character('a'));

    m.put(new Integer(3), new Character('b'));

    m.put(new Integer(5), new Character('c'));

    m.put(new Integer(7), new Character('d'));

    m.put(new Integer(11), new Character('e'));

    System.out.println("m: " + m);

    interp.set("m", m);

    interp.exec("print m, m.__class__, " +

      "m[1], m[1].__class__");

    // Not a Python dictionary, so this fails:

    //! interp.exec("for x in m.keys():" +

    //!   "print x, m[x]");

    // To convert a Map to a Python dictionary,

    // use com.bruceeckel.python.PyUtil:

    interp.set("m", PyUtil.toPyDictionary(m));

    interp.exec("print m, m.__class__, " +

      "m[1], m[1].__class__");

    interp.exec("for x in m.keys():print x,m[x]");

  }

  public static void

  main(String[] args) throws PyException  {

    junit.textui.TestRunner.run(

      PythonInterpreterSetting.class);

  }

} ///:~

#[BT_316]#

#[BT_317]#As usual with Java, the distinction between real objects and primitive types causes trouble. In general, if you pass a regular object to set( ), it knows what to do with it, but if you want to pass in a primitive you must perform a conversion. One way to do this is to create a “Py” type, such as PyInteger or PyFloat. but it turns out you can also use Java’s own object wrappers like Integer and Float, which is probably going to be a lot easier to remember.

#[BT_318]#Early in the program you’ll see an exec( ) containing the Python statement:

print a[5:]

#[BT_319]#The colon inside the indexing statement indicates a Python slice, which produces a range of elements from the original array. In this case, it produces an array containing the elements from number 5 until the end of the array. You could also say ‘a[3:5]’ to produce elements 3 through 5, or ‘a[:5]’ to produce the elements zero through 5. The reason a slice is used in this statement is to make sure that the Java String has really been converted to a Python string, which can also be treated as an array of characters.

#[BT_320]#You can see that it’s possible, using exec( ), to create a Python function (although it’s a bit awkward). The prt( ) function prints the whole array, and then (to make sure it’s a real Python array), iterates through each element of the array and prints it. Finally, it prints the class of the array, so we can see what conversion has taken place (Python not only has run-time type information, it also has the equivalent of Java reflection). The prt( ) function is used to print arrays that come from each of the Java primitive types.

#[BT_321]#Although a Java ArrayList does pass into the interpreter using set( ), and you can index into it as if it were an array, trying to create a slice fails. To completely convert it into an array, one approach is to simply extract a Java array using toArray( ), and pass that in. The set( ) method converts it to a PyArray – one of the classes provided with Jython – which can be treated as a Python array (you can also explicitly create a PyArray, but this seems unnecessary).

#[BT_322]#Finally, a Map is created and passed directly into the interpreter. While it is possible to do simple things like index into the resulting object, it’s not a real Python dictionary so you can’t (for example) call the keys( ) method. There is no straightforward way to convert a Java Map into a Python dictionary, and so I wrote a utility called toPyDictionary( ) and made it a static method of com.bruceeckel.python.PyUtil. This also includes utilities to extract a Python array into a Java List, and a Python dictionary into a Java Map:

//- com:bruceeckel:python:PyUtil.java

// PythonInterpreter utilities

package com.bruceeckel.python;

import org.python.util.PythonInterpreter;

import org.python.core.*;

import java.util.*;

 

public class PyUtil {

  /** Extract a Python tuple or array into a Java

  List (which can be converted into other kinds

  of lists and sets inside Java).

  @param interp The Python interpreter object

  @param pyName The id of the python list object

  */

  public static List

  toList(PythonInterpreter interp, String pyName){

    return new ArrayList(Arrays.asList(

      (Object[])interp.get(

        pyName, Object[].class)));

  }

  /** Extract a Python dictionary into a Java Map

  @param interp The Python interpreter object

  @param pyName The id of the python dictionary

  */

  public static Map

  toMap(PythonInterpreter interp, String pyName){

    PyList pa = ((PyDictionary)interp.get(

      pyName)).items();

    Map map = new HashMap();

    while(pa.__len__() != 0) {

      PyTuple po = (PyTuple)pa.pop();

      Object first = po.__finditem__(0)

        .__tojava__(Object.class);

      Object second = po.__finditem__(1)

        .__tojava__(Object.class);

      map.put(first, second);

    }

    return map;

  }

  /** Turn a Java Map into a PyDictionary,

  suitable for placing into a PythonInterpreter

  @param map The Java Map object

  */

  public static PyDictionary

  toPyDictionary(Map map) {

    Map m = new HashMap();

    Iterator it = map.entrySet().iterator();

    while(it.hasNext()) {

      Map.Entry e = (Map.Entry)it.next();

      m.put(Py.java2py(e.getKey()),

        Py.java2py(e.getValue()));

    }

    // PyDictionary constructor wants a Hashtable:

    return new PyDictionary(new Hashtable(m));

  }

} ///:~

#[BT_323]#

#[BT_324]#Here is the (black-box) unit testing code:

//- com:bruceeckel:python:Test.java

package com.bruceeckel.python;

import org.python.util.PythonInterpreter;

import java.util.*;

import junit.framework.*;

 

public class Test extends TestCase  {

  PythonInterpreter pi =

    new PythonInterpreter();

  public void test1() {

    pi.exec("tup=('fee','fi','fo','fum','fi')");

    List lst = PyUtil.toList(pi, "tup");

    System.out.println(lst);

    System.out.println(new HashSet(lst));

  }

  public void test2() {

    pi.exec("ints=[1,3,5,7,9,11,13,17,19]");

    List lst = PyUtil.toList(pi, "ints");

    System.out.println(lst);

  }

  public void test3() {

    pi.exec("dict = { 1 : 'a', 3 : 'b', " +

      "5 : 'c', 9 : 'd', 11 : 'e'}");

    Map mp = PyUtil.toMap(pi, "dict");

    System.out.println(mp);

  }

  public void test4() {

    Map m = new HashMap();

    m.put("twas", new Integer(11));

    m.put("brillig", new Integer(27));

    m.put("and", new Integer(47));

    m.put("the", new Integer(42));

    m.put("slithy", new Integer(33));

    m.put("toves", new Integer(55));

    System.out.println(m);

    pi.set("m", PyUtil.toPyDictionary(m));

    pi.exec("print m");

    pi.exec("print m['slithy']");

  }

  public static void main(String args[]) {

    junit.textui.TestRunner.run(Test.class);

  }

} ///:~

#[BT_325]#

#[BT_326]#We’ll see the use of the extraction tools in the next section.

Getting data out

#[BT_327]#There are a number of different ways to extract data from the PythonInterpreter. If you simply call the get( ) method, passing it the object identifier as a string, it returns a PyObject (part of the org.python.core support classes). It’s possible to “cast” it using the __tojava__( ) method, but there are better alternatives:

1.              The convenience methods in the Py class, such as py2int( ), take a PyObject and convert it to a number of different types.

2.              An overloaded version of get( ) takes the desired Java Class object as a second argument, and produces an object that has that run-time type (so you still need to perform a cast on the result in your Java code).

#[BT_328]#Using the second approach, getting an array from the PythonInterpreter is quite easy. This is especially useful because Python is exceptionally good at manipulating strings and files, and so you will commonly want to extract the results as an array of strings. For example, you can do a wildcard expansion of file names using Python’s glob( ), as shown further down in the following code:

//- interpreter:PythonInterpreterGetting.java

// Getting data from the PythonInterpreter object.

package interpreter;

import org.python.util.PythonInterpreter;

import org.python.core.*;

import java.util.*;

import com.bruceeckel.python.*;

import junit.framework.*;

 

public class

PythonInterpreterGetting extends TestCase {

  PythonInterpreter interp =

    new PythonInterpreter();

  public void test() throws PyException  {

    interp.exec("a = 100");

    // If you just use the ordinary get(),

    // it returns a PyObject:

    PyObject a = interp.get("a");

    // There's not much you can do with a generic

    // PyObject, but you can print it out:

    System.out.println("a = " + a);

    // If you know the type it's supposed to be,

    // you can "cast" it using __tojava__() to

    // that Java type and manipulate it in Java.

    // To use 'a' as an int, you must use

    // the Integer wrapper class:

    int ai= ((Integer)a.__tojava__(Integer.class))

      .intValue();

    // There are also convenience functions:

    ai = Py.py2int(a);

    System.out.println("ai + 47 = " + (ai + 47));

    // You can convert it to different types:

    float af = Py.py2float(a);

    System.out.println("af + 47 = " + (af + 47));

    // If you try to cast it to an inappropriate

    // type you'll get a runtime exception:

    //! String as = (String)a.__tojava__(

    //!   String.class);

   

    // If you know the type, a more useful method

    // is the overloaded get() that takes the

    // desired class as the 2nd argument:

    interp.exec("x = 1 + 2");

    int x = ((Integer)interp

      .get("x", Integer.class)).intValue();

    System.out.println("x = " + x);

   

    // Since Python is so good at manipulating

    // strings and files, you will often need to

    // extract an array of Strings. Here, a file

    // is read as a Python array:

    interp.exec("lines = " +

      "open('PythonInterpreterGetting.java')" +

      ".readlines()");

    // Pull it in as a Java array of String:

    String[] lines = (String[])

      interp.get("lines", String[].class);

    for(int i = 0; i < 10; i++)

      System.out.print(lines[i]);

   

    // As an example of useful string tools,

    // global expansion of ambiguous file names

    // using glob is very useful, but it's not

    // part of the standard Jython package, so

    // you'll have to make sure that your

    // Python path is set to include these, or

    // that you deliver the necessary Python

    // files with your application.

    interp.exec("from glob import glob");

    interp.exec("files = glob('*.java')");

    String[] files = (String[])

      interp.get("files", String[].class);

    for(int i = 0; i < files.length; i++)

      System.out.println(files[i]);

   

    // You can extract tuples and arrays into

    // Java Lists with com.bruceeckel.PyUtil:

    interp.exec(

      "tup = ('fee', 'fi', 'fo', 'fum', 'fi')");

    List tup = PyUtil.toList(interp, "tup");

    System.out.println(tup);

    // It really is a list of String objects:

    System.out.println(tup.get(0).getClass());

    // You can easily convert it to a Set:

    Set tups = new HashSet(tup);

    System.out.println(tups);

    interp.exec("ints=[1,3,5,7,9,11,13,17,19]");

    List ints = PyUtil.toList(interp, "ints");

    System.out.println(ints);

    // It really is a List of Integer objects:

    System.out.println((ints.get(1)).getClass());

   

    // If you have a Python dictionary, it can

    // be extracted into a Java Map, again with

    // com.bruceeckel.PyUtil:

    interp.exec("dict = { 1 : 'a', 3 : 'b'," +

      "5 : 'c', 9 : 'd', 11 : 'e' }");

    Map map = PyUtil.toMap(interp, "dict");

    System.out.println("map: " + map);

    // It really is Java objects, not PyObjects:

    Iterator it = map.entrySet().iterator();

    Map.Entry e = (Map.Entry)it.next();

    System.out.println(e.getKey().getClass());

    System.out.println(e.getValue().getClass());

  }

  public static void

  main(String[] args) throws PyException  {

    junit.textui.TestRunner.run(

      PythonInterpreterGetting.class);

  }

} ///:~

#[BT_329]#

#[BT_330]#The last two examples show the extraction of Python tuples and lists into Java Lists, and Python dictionaries into Java Maps. Both of these cases require more processing than is provided in the standard Jython library, so I have again created utilities in com.bruceeckel.pyton.PyUtil: toList( ) to produce a List from a Python sequence, and toMap( ) to produce a Map from a Python dictionary. The PyUtil methods make it easier to take important data structures back and forth between Java and Python.

Multiple interpreters

#[BT_331]#It’s also worth noting that you can have multiple PythonInterpreter objects in a program, and each one has its own name space:

//- interpreter:MultipleJythons.java

// You can run multiple interpreters, each

// with its own name space.

package interpreter;

import org.python.util.PythonInterpreter;

import org.python.core.*;

import junit.framework.*;

 

public class MultipleJythons extends TestCase  {

  PythonInterpreter

    interp1 =  new PythonInterpreter(),

    interp2 =  new PythonInterpreter();

  public void test() throws PyException {

    interp1.set("a", new PyInteger(42));

    interp2.set("a", new PyInteger(47));

    interp1.exec("print a");

    interp2.exec("print a");

    PyObject x1 = interp1.get("a");

    PyObject x2 = interp2.get("a");

    System.out.println("a from interp1: " + x1);

    System.out.println("a from interp2: " + x2);

  }

  public static void

  main(String[] args) throws PyException  {

    junit.textui.TestRunner.run(MultipleJythons.class);

  }

} ///:~

#[BT_332]#

#[BT_333]#When you run the program you’ll see that the value of a is distinct within each PythonInterpreter.

Controlling Java from Jython

#[BT_334]#Since you have the Java language at your disposal, and you can set and retrieve values in the interpreter, there’s a tremendous amount that you can accomplish with the above approach (controlling Python from Java).  But one of the amazing things about Jython is that it makes Java classes almost transparently available from within Jython. Basically, a Java class looks like a Python class. This is true for standard Java library classes as well as classes that you create yourself, as you can see here:

## interpreter:JavaClassInPython.py

#=M jython.bat JavaClassInPython.py

# Using Java classes within Jython

from java.util import Date, HashSet, HashMap

from interpreter.javaclass import JavaClass

from math import sin

 

d = Date() # Creating a Java Date object

print d # Calls toString()

 

# A "generator" to easily create data:

class ValGen:

  def __init__(self, maxVal):

    self.val = range(maxVal)

  # Called during 'for' iteration:

  def __getitem__(self, i):

    # Returns a tuple of two elements:

    return self.val[i], sin(self.val[i])

 

# Java standard containers:

map = HashMap()

set = HashSet()

 

for x, y in ValGen(10):

  map.put(x, y)

  set.add(y)

  set.add(y)

 

print map

print set

 

# Iterating through a set:

for z in set:

  print z, z.__class__

 

print map[3] # Uses Python dictionary indexing

for x in map.keySet(): # keySet() is a Map method

  print x, map[x]

 

# Using a Java class that you create yourself is

# just as easy:

jc = JavaClass()

jc2 = JavaClass("Created within Jython")

print jc2.getVal()

jc.setVal("Using a Java class is trivial")

print jc.getVal()

print jc.getChars()

jc.val = "Using bean properties"

print jc.val

##~

#[BT_335]#The “=M” comment is recognized by the makefile generator tool (that I created for this book) as a replacement makefile command. This will be used instead of the commands that the extraction tool would normally place in the makefile.

#[BT_336]#Note that the import statements map to the Java package structure exactly as you would expect. In the first example, a Date( ) object is created as if it were a native Python class, and printing this object just calls toString( ).

#[BT_337]#ValGen implements the concept of a “generator” which is used a great deal in the C++ STL (Standard Template Library, part of the Standard C++ Library). A generator is an object that produces a new object every time its “generation method” is called, and it is quite convenient for filling containers. Here, I wanted to use it in a for iteration, and so I needed the generation method to be the one that is called by the iteration process. This is a special method called __getitem__( ), which is actually the overloaded operator for indexing, ‘[ ]’. A for loop calls this method every time it wants to move the iteration forward, and when the elements run out, __getitem__( ) throws an out-of-bounds exception and that signals the end of the for loop (in other languages, you would never use an exception for ordinary control flow, but in Python it seems to work quite well). This exception happens automatically when self.val[i] runs out of elements, so the __getitem__( ) code turns out to be simple. The only complexity is that __getitem__( ) appears to return two objects instead of just one. What Python does is automatically package multiple return values into a tuple, so you still only end up returning a single object (in C++ or Java you would have to create your own data structure to accomplish this). In addition, in the for loop where ValGen is used, Python automatically “unpacks” the tuple so that you can have multiple iterators in the for. These are the kinds of syntax simplifications that make Python so endearing.

#[BT_338]#The map and set objects are instances of Java’s HashMap and HashSet, again created as if those classes were just native Python components. In the for loop, the put( ) and add( ) methods work just like they do in Java. Also, indexing into a Java Map uses the same notation as for dictionaries, but note that to iterate through the keys in a Map you must use the Map method keySet( ) rather than the Python dictionary method keys( ).

#[BT_339]#The final part of the example shows the use of a Java class that I created from scratch, to demonstrate how trivial it is. Notice also that Jython intuitively understands JavaBeans properties, since you can either use the getVal( ) and setVal( ) methods, or assign to and read from the equivalent val property. Also, getChars( ) returns a Character[] in Java, and this becomes an array in Python.

#[BT_340]#The easiest way to use Java classes that you create for use inside a Python program is to put them inside a package. Although Jython can also import unpackaged java classes (import JavaClass), all such unpackaged java classes will be treated as if they were defined in different packages so they can only see each other’s public methods.

#[BT_341]#Java packages translate into Python modules, and Python must import a module in order to be able to use the Java class. Here is the Java code for JavaClass:

//- interpreter:javaclass:JavaClass.java

package interpreter.javaclass;

import junit.framework.*;

import com.bruceeckel.util.*;

 

public class JavaClass {

  private String s = "";

  public JavaClass() {

    System.out.println("JavaClass()");

  }

  public JavaClass(String a) {

    s = a;

    System.out.println("JavaClass(String)");

  }

  public String getVal() {

    System.out.println("getVal()");

    return s;

  }

  public void setVal(String a) {

    System.out.println("setVal()");

    s = a;

  }

  public Character[] getChars() {

    System.out.println("getChars()");

    Character[] r = new Character[s.length()];

    for(int i = 0; i < s.length(); i++)

      r[i] = new Character(s.charAt(i));

    return r;

  }

  public static class Test extends TestCase  {

    JavaClass

      x1 = new JavaClass(),

      x2 = new JavaClass("UnitTest");

    public void test1() {

      System.out.println(x2.getVal());

      x1.setVal("SpamEggsSausageAndSpam");

      System.out.println(

        Arrays2.toString(x1.getChars()));

    }

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(Test.class);

  }

} ///:~

#[BT_342]#

#[BT_343]#You can see that this is just an ordinary Java class, without any awareness that it will be used in a Jython program. For this reason, one of the important uses of Jython is in testing Java code[10]. Because Python is such a powerful, flexible, dynamic language it is an ideal tool for automated test frameworks, without making any changes to the Java code that’s being tested.

Inner Classes

#[BT_344]#Inner classes becomes attributes on the class object. Instances of static inner classes can be create by the usual call:

com.foo.JavaClass.StaticInnerClass()

#[BT_345]#Non-static inner classes must have an outer class instance supplied explicitly as the first argument:

com.foo.JavaClass.InnerClass(com.foo.JavaClass())

Using Java libraries

#[BT_346]#Jython wraps the Java libraries so that any of them can be used directly or via inheritance. In addition, Python shorthand simplifies coding.

#[BT_347]#As an example, consider the HTMLButton.java example from Chapter 9 of Thinking in Java, 2nd edition (you presumably have already downloaded and installed the source code for that book from www.BruceEckel.com, since a number of examples in this book use libraries from that book). Here is its conversion to Jython:

## interpreter:PythonSwing.py

# The HTMLButton.java example from

# "Thinking in Java, 2nd edition," Chapter 13,

# converted into Jython.

# Don’t run this as part of the automatic make:

#=M @echo skipping PythonSwing.py

from javax.swing import JFrame, JButton, JLabel

from java.awt import FlowLayout

 

frame = JFrame("HTMLButton", visible=1,

  defaultCloseOperation=JFrame.EXIT_ON_CLOSE)

 

def kapow(e):

  frame.contentPane.add(JLabel("<html>"+

    "<i><font size=+4>Kapow!"))

  # Force a re-layout to

  # include the new label:

  frame.validate()

 

button = JButton("<html><b><font size=+2>" +

  "<center>Hello!<br><i>Press me now!",

  actionPerformed=kapow)

frame.contentPane.layout = FlowLayout()

frame.contentPane.add(button)

frame.pack()

frame.size=200, 500

##~

#[BT_348]#If you compare the Java version of the program to the above Jython implementation, you’ll see that Jython is shorter and generally easier to understand. For example, in the Java version to set up the frame you had to make several calls: the constructor for JFrame( ), the setVisible( ) method and the setDefaultCloseOperation( ) method, whereas in the above code all three of these operations are performed with a single constructor call.

#[BT_349]#Also notice that the JButton is configured with an actionListener( ) method inside the constructor, with the assignment to kapow. In addition, Jython’s JavaBean awareness means that a call to any method with a name that begins with “set” can be replaced with an assignment, as you can see above.

#[BT_350]#The only method that did not come over from Java is the pack( ) method, which seems to be essential in order to force the layout to happen properly. It’s also important that the call to pack( ) appear before the size setting.

Inheriting from Java library classes

#[BT_351]#You can easily inherit from standard Java library classes in Jython. Here’s the Dialogs.java example from Chapter 13 of Thinking in Java, 2nd edition, converted into Jython:

## interpreter:PythonDialogs.py

# Dialogs.java from "Thinking in Java, 2nd

# edition," Chapter 13, converted into Jython.

# Don’t run this as part of the automatic make:

#=M @echo skipping PythonDialogs.py

from java.awt import FlowLayout

from javax.swing import JFrame, JDialog, JLabel

from javax.swing import JButton

 

class MyDialog(JDialog):

  def __init__(self, parent=None):

    JDialog.__init__(self,

      title="My dialog", modal=1)

    self.contentPane.layout = FlowLayout()

    self.contentPane.add(JLabel("A dialog!"))

    self.contentPane.add(JButton("OK",

      actionPerformed =

        lambda e, t=self: t.dispose()))

    self.pack()

 

frame = JFrame("Dialogs", visible=1,

  defaultCloseOperation=JFrame.EXIT_ON_CLOSE)

dlg = MyDialog()

frame.contentPane.add(

  JButton("Press here to get a Dialog Box",

    actionPerformed = lambda e: dlg.show()))

frame.pack()

##~

#[BT_352]#MyDialog is inherited from JDialog, and you can see named arguments being used in the call to the base-class constructor.

#[BT_353]#In the creation of the “OK” JButton, note that the actionPerformed method is set right inside the constructor, and that the function is created using the Python lambda keyword. This creates a nameless function with the arguments appearing before the colon and the expression that generates the returned value after the colon. As you should know, the Java prototype for the actionPerformed( ) method only contains a single argument, but the lambda expression indicates two. However, the second argument is provided with a default value, so the function can be called with only one argument. The reason for the second argument is seen in the default value, because this is a way to pass self into the lambda expression, so that it can be used to dispose of the dialog.

#[BT_354]#Compare this code with the version that’s published in Thinking in Java, 2nd edition. You’ll find that Python language features allow a much more succinct and direct implementation.

Creating Java classes with Jython

#[BT_355]#Although it does not directly relate to the original problem of this chapter (creating an interpreter), Jython has the additional ability to create Java classes directly from your Jython code. This can produce very useful results, as you are then able to treat the results as if they are native Java classes, albeit with Python power under the hood.

#[BT_356]#To produce Java classes from Python code, Jython comes with a compiler called jythonc.

#[BT_357]#The process of creating Python classes that will produce Java classes is a bit more complex than when calling Java classes from Python, because the methods in Java classes are strongly typed, while Python functions and methods are weakly typed. Thus, you must somehow tell jythonc that a Python method is intended to have a particular set of argument types and that its return value is a particular type. You accomplish this with the “@sig” string, which is placed right after the beginning of the Python method definition (this is the standard location for the Python documentation string). For example:

  def returnArray(self):

    "@sig public java.lang.String[] returnArray()"

#[BT_358]#The Python definition doesn’t specify any return type, but the @sig string gives the full type information about what is being passed and returned. The jythonc compiler uses this information to generate the correct Java code.

#[BT_359]#There’s one other set of rules you must follow in order to get a successful compilation: you must inherit from a Java class or interface in your Python class (you do not need to specify the @sig signature for methods defined in the superclass/interface). If you do not do this, you won’t get your desired methods – unfortunately, jythonc gives you no warnings or errors in this case, but you won’t get what you want. If you don’t see what’s missing, it can be very frustrating.

#[BT_360]#In addition, you must import the appropriate java class and give the correct package specification.  In the example below, java is imported so you must inherit from java.lang.Object, but you could also say from java.lang import Object and then you’d just inherit from Object without the package specification. Unfortunately, you don’t get any warnings or errors if you get this wrong, so you must be patient and keep trying.

#[BT_361]#Here is an example of a Python class created to produce a Java class. This also introduces the ‘=T’ directive for the makefile builder tool, which specifies a different target than the one that is normally used by the tool. In this case, the Python file is used to build a Java .class file, so the class file is the desired makefile target. To accomplish this, the default makefile command is replaced using the ‘=M’ directive (notice how you can break across lines using ‘\’):

## interpreter:PythonToJavaClass.py

#=T python\java\test\PythonToJavaClass.class

#=M jythonc.bat --package python.java.test \

#=M PythonToJavaClass.py

# A Python class created to produce a Java class

from jarray import array

import java

 

class PythonToJavaClass(java.lang.Object):

  # The '@sig' signature string is used to create

  # the proper signature in the resulting

  # Java code:

  def __init__(self):

    "@sig public PythonToJavaClass()"

    print "Constructor for PythonToJavaClass"

 

  def simple(self):

    "@sig public void simple()"

    print "simple()"

 

  # Returning values to Java:

  def returnString(self):

    "@sig public java.lang.String returnString()"

    return "howdy"

 

  # You must construct arrays to return along

  # with the type of the array:

  def returnArray(self):

    "@sig public java.lang.String[] returnArray()"

    test = [ "fee", "fi", "fo", "fum" ]

    return array(test, java.lang.String)

   

  def ints(self):

    "@sig public java.lang.Integer[] ints()"

    test = [ 1, 3, 5, 7, 11, 13, 17, 19, 23 ]

    return array(test, java.lang.Integer)

 

  def doubles(self):

    "@sig public java.lang.Double[] doubles()"

    test = [ 1, 3, 5, 7, 11, 13, 17, 19, 23 ]

    return array(test, java.lang.Double)

 

  # Passing arguments in from Java:

  def argIn1(self, a):

    "@sig public void argIn1(java.lang.String a)"

    print "a: %s" % a

    print "a.__class__", a.__class__

 

  def argIn2(self, a):

    "@sig public void argIn1(java.lang.Integer a)"

    print "a + 100: %d" % (a + 100)

    print "a.__class__", a.__class__

 

  def argIn3(self, a):

    "@sig public void argIn3(java.util.List a)"

    print "received List:", a, a.__class__

    print "element type:", a[0].__class__

    print "a[3] + a[5]:", a[5] + a[7]

    #! print "a[2:5]:", a[2:5] # Doesn't work

   

  def argIn4(self, a):

    "@sig public void \

       argIn4(org.python.core.PyArray a)"

    print "received type:", a.__class__

    print "a: ", a

    print "element type:", a[0].__class__

    print "a[3] + a[5]:", a[5] + a[7]

    print "a[2:5]:", a[2:5] # A real Python array

   

  # A map must be passed in as a PyDictionary:

  def argIn5(self, m):

    "@sig public void \

       argIn5(org.python.core.PyDictionary m)"

    print "received Map: ", m, m.__class__

    print "m['3']:", m['3']

    for x in m.keys():

      print x, m[x]

##~

#[BT_362]#First note that PythonToJavaClass is inherited from java.lang.Object; if you don’t do this you will quietly get a Java class without the right signatures. You are not required to inherit from Object; any other Java class will do.

#[BT_363]#This class is designed to demonstrate different  arguments and return values, to provide you with enough examples that you’ll be able to easily create your own signature strings. The first three of these are fairly self-explanatory, but note the full qualification of the Java name in the signature string.

#[BT_364]#In returnArray( ), a Python array must be returned as a Java array. To do this, the Jython array( ) function (from the jarray module) must be used, along with the type of the class for the resulting array. Any time you need to return an array to Java, you must use array( ), as seen in the methods ints( ) and doubles( ).

#[BT_365]#The last methods show how to pass arguments in from Java. Basic types happen automatically as long as you specify them in the @sig string, but you must use objects and you cannot pass in primitives (that is, primitives must be ensconced in wrapper objects, such as Integer).

#[BT_366]#In argIn3( ), you can see that a Java List is transparently converted to something that behaves just like a Python array, but is not a true array because you cannot take a slice from it. If you want a true Python array, then you must create and pass a PyArray as in argIn4( ), where the slice is successful. Similarly, a Java Map must come in as a PyDictionary in order to be treated as a Python dictionary.

#[BT_367]#Here is the Java program to exercise the Java classes produced by the above Python code. This also introduces the ‘=D’ directive for the makefile builder tool, which specifies a dependency in addition to those detected by the tool. Here, you can’t compile TestPythonToJavaClass.java until PythonToJavaClass.class is available:

//- interpreter:TestPythonToJavaClass.java

//+D python\java\test\PythonToJavaClass.class

package interpreter;

import java.lang.reflect.*;

import java.util.*;

import org.python.core.*;

import junit.framework.*;

import com.bruceeckel.util.*;

import com.bruceeckel.python.*;

// The package with the Python-generated classes:

import python.java.test.*;

 

public class

TestPythonToJavaClass extends TestCase  {

  PythonToJavaClass p2j = new PythonToJavaClass();

  public void testDumpClassInfo() {

    System.out.println(

      Arrays2.toString(

        p2j.getClass().getConstructors()));

    Method[] methods =

      p2j.getClass().getMethods();

    for(int i = 0; i < methods.length; i++) {

      String nm = methods[i].toString();

      if(nm.indexOf("PythonToJavaClass") != -1)

        System.out.println(nm);

    }

  }

  public void test1() {

    p2j.simple();

    System.out.println(p2j.returnString());

    System.out.println(

      Arrays2.toString(p2j.returnArray()));

    System.out.println(

      Arrays2.toString(p2j.ints());

    System.out.println(

      Arrays2.toString(p2j.doubles()));

    p2j.argIn1("Testing argIn1()");

    p2j.argIn2(new Integer(47));

    ArrayList a = new ArrayList();

    for(int i = 0; i < 10; i++)

      a.add(new Integer(i));

    p2j.argIn3(a);

    p2j.argIn4(

      new PyArray(Integer.class, a.toArray()));

    Map m = new HashMap();

    for(int i = 0; i < 10; i++)

      m.put("" + i, new Float(i));

    p2j.argIn5(PyUtil.toPyDictionary(m));

  }

  public static void main(String[] args) {

    junit.textui.TestRunner.run(

      TestPythonToJavaClass.class);

  }

} ///:~

#[BT_368]#

#[BT_369]#For Python support, you’ll usually only need to import the classes in org.python.core. Everything else in the above example is fairly straightforward, as PythonToJavaClass appears, from the Java side, to be just another Java class. dumpClassInfo( ) uses reflection to verify that the method signatures specified in PythonToJavaClass.py have come through properly.

Building the Java classes from the Python code

#[BT_370]#Part of the trick of creating Java classes from Python code is the @sig information in the method documentation strings. But there’s a second problem which stems from the fact that Python has no “package” keyword – the Python equivalent of packages (modules) are implicitly created based on the file name. However, to bring the resulting class files into the Java program, jythonc must be given information about how to create the Java package for the Python code. This is done on the jythonc command line using the --package flag, followed by the package name you wish to produce (including the separation dots, just as you would give the package name using the package keyword in a Java program). This will put the resulting .class files in the appropriate subdirectory off of the current directory. Then you only need to import the package in your Java program, as shown above (you’ll need ‘.’ in your CLASSPATH in order to run it from the code directory).

#[BT_371]#Here are the make dependency rules that I used to build the above example (the backslashes at the ends of the lines are understood by make to be line continuations). These rules are encoded into the above Java and Python files using the comment syntax that’s understood by my makefile builder tool:

TestPythonToJavaClass.class: \

        TestPythonToJavaClass.java \

        python\java\test\PythonToJavaClass.class

    javac TestPythonToJavaClass.java

 

python\java\test\PythonToJavaClass.class: \

        PythonToJavaClass.py

    jythonc.bat --package python.java.test \

    PythonToJavaClass.py

#[BT_372]#The first target, TestPythonToJavaClass.class, depends on both TestPythonToJavaClass.java and the PythonToJavaClass.class, which is the Python code that’s converted to a class file. This latter, in turn, depends on the Python source code. Note that it’s important that the directory where the target lives be specified, so that the makefile will create the Java program with the minimum necessary amount of rebuilding.

The Java-Python Extension (JPE)

#[BT_373]#An alternative to Jython is the Java-Python Extension (JPE), which directly connects with your native C-Python implementation.

#[BT_374]#Jython runs entirely within the JavaVM, which produces two fundamental limitations: Jython cannot be called from CPython, and native Python extensions are not accessible from JPython. JPE is linked with the Python C libraries, so JPE can be called from C-Python, and native Python extensions can be called from Java through JPE.

#[BT_375]#If you need to access the features on your native platform, JPE might be the easiest solution. You can find JPE at http://www.arakne.com/jpe.htm.

Summary

#[BT_376]#This chapter has arguably gone much deeper into Jython than required to use the interpreter design pattern. Indeed, once you decide that you need to use interpreter and that you’re not going to get lost inventing your own language, the solution of installing Jython is quite simple, and you can at least get started by following the GreenHouseController example.

#[BT_377]#Of course, that example is often too simple and you may need something more sophisticated, often requiring more interesting data to be passed back and forth. When I encountered the limited documentation, I felt it necessary to come up with a more thorough examination of Jython.

#[BT_378]#In the process, note that there could be another equally powerful design pattern lurking in here, which could perhaps be called multiple languages. This is based on the experience of having each language solve a certain class of problems better than the other; by combining languages you can solve problems much faster than with either language by itself. CORBA is another way to bridge across languages, and at the same time bridging between computers and operating systems.

#[BT_379]#To me, Python and Java present a very potent combination for program development because of Java’s architecture and tool set, and Python’s extremely rapid development (generally considered to be 5-10 times faster than C++ or Java). Python is usually slower, however, but even if you end up re-coding parts of your program for speed, the initial fast development will allow you to more quickly flesh out the system and uncover and solve the critical sections. And often, the execution speed of Python is not a problem – in those cases it’s an even bigger win. A number of commercial products already use Java and Jython, and because of the terrific productivity leverage I expect to see this happen more in the future.

Exercises

             1.             Modify GreenHouseLanguage.py so that it checks the times for the events and runs those events at the appropriate times.

             2.             Modify GreenHouseLanguage.py so that it calls a function for action instead of just printing a string.

             3.             Create a Swing application with a JTextField (where the user will enter commands) and a JTextArea (where the command results will be displayed). Connect to a PythonInterpreter object so that the output will be sent to the JTextArea (which should scroll). You’ll need to locate the PythonInterpreter command that redirects the output to a Java stream.

             4.             Modify GreenHouseLanguage.py to add a master controller class (instead of the static array inside Event) and provide a run( ) method for each of the subclasses. Each run( ) should create and use an object from the standard Java library during its execution. Modify GreenHouseController.java to use this new class.

             5.             Modify the resulting GreenHouseLanguage.py from exercise two to produce Java classes (add the @sig documentation strings to produce the correct Java signatures, and create a makefile to build the Java .class files). Write a Java program that uses these classes.

#[BT_380]#


Complex system states

StateMachine

#[BT_106]#While State has a way to allow the client programmer to change the implementation, StateMachine imposes a structure to automatically change the implementation from one object to the next. The current implementation represents the state that a system is in, and the system behaves differently from one state to the next (because it uses State). Basically, this is a “state machine” using objects.

#[BT_107]#The code that moves the system from one state to the next is often a Template Method, as seen in the following framework for a basic state machine. We start by defining a tagging interface for input objects:

//: statemachine:Input.java

// Inputs to a state machine

package statemachine;

 

public interface Input {} ///:~

Each state can be run( ) to perform its behavior, and (in this design) you can also pass it an Input object so it can tell you what new state to move to based on that Input. The key distinction between this design and the next is that here, each State object decides what other states it can move to, based on the Input, whereas in the subsequent design all of the state transitions are held in a single table. Another way to put it is that here, each State object has its own little State table, and in the subsequent design there is a single master state transition table for the whole system.

//: statemachine:State.java

// A State has an operation, and can be moved

// into the next State given an Input:

package statemachine;

 

public interface State {

  void run();

  State next(Input i);

} ///:~

The StateMachine keeps track of the current state, which is initialized by the constructor. The runAll( ) method takes an Iterator to a list of Input objects (an Iterator is used here for convenience and simplicity; the important issue is that the input information comes from somewhere). This method not only moves to the next state, but it also calls run( ) for each state object – thus you can see it’s an expansion of the idea of the State pattern, since run( ) does something different depending on the state that the system is in.

//: statemachine:StateMachine.java

// Takes an Iterator of Inputs to move from State

// to State using a template method.

package statemachine;

import java.util.*;

 

public class StateMachine {

  private State currentState;

  public StateMachine(State initialState) {

    currentState = initialState;

    currentState.run();

  }

  // Template method:

  public final void runAll(Iterator inputs) {

    while(inputs.hasNext()) {

      Input i = (Input)inputs.next();

      System.out.println(i);

      currentState = currentState.next(i);

      currentState.run();

    }

  }

}  ///:~

 

I’ve also treated runAll( ) as a template method. This is typical, but certainly not required – you could concievably want to override it, but typically the behavior change will occur in State’s run( ) instead.

At this point the basic framework for this style of StateMachine (where each state decides the next states) is complete. As an example, I’ll use a fancy mousetrap that can move through several states in the process of trapping a mouse[11]. The mouse classes and information are stored in the mouse package, including a class representing all the possible moves that a mouse can make, which will be the inputs to the state machine:

//: statemachine:mouse:MouseAction.java

package statemachine.mouse;

import java.util.*;

import statemachine.*;

 

public class MouseAction implements Input {

  private String action;

  private static List instances = new ArrayList();

  private MouseAction(String a) {

    action = a;

    instances.add(this);

  }

  public String toString() { return action; }

  public int hashCode() {

    return action.hashCode();

  }

  public boolean equals(Object o) {

    return (o instanceof MouseAction)

      && action.equals(((MouseAction)o).action);

  }

  public static MouseAction forString(String description) {

    Iterator it = instances.iterator();

    while(it.hasNext()) {

      MouseAction ma = (MouseAction)it.next();

      if(ma.action.equals(description))

        return ma;

    }

    throw new RuntimeException("not found: " + description);

  }

  public static MouseAction

    appears = new MouseAction("mouse appears"),

    runsAway = new MouseAction("mouse runs away"),

    enters = new MouseAction("mouse enters trap"),

    escapes = new MouseAction("mouse escapes"),

    trapped = new MouseAction("mouse trapped"),

    removed = new MouseAction("mouse removed");

} ///:~

 

You’ll note that hashCode( ) and equals( ) have been overriden so that MouseAction objects can be used as keys in a HashMap, but in the first version of the mousetrap we won’t do this. Also, each possible move by a mouse is enumerated as a static MouseAction object.

For creating test code, a sequence of mouse inputs is provided from a text file:

//:! statemachine:mouse:MouseMoves.txt

mouse appears

mouse runs away

mouse appears

mouse enters trap

mouse escapes

mouse appears

mouse enters trap

mouse trapped

mouse removed

mouse appears

mouse runs away

mouse appears

mouse enters trap

mouse trapped

mouse removed

///:~

To read this file in a generic fashion, here is a general-purpose tool called StringList:

//: com:bruceeckel:util:StringList.java

// General-purpose tool that reads a file of text

// lines into a List, one line per list.

package com.bruceeckel.util;

import java.io.*;

import java.util.*;

 

public class StringList extends ArrayList {

  public StringList(String textFilePath) {

    try {

      BufferedReader inputs = new BufferedReader (

        new FileReader(textFilePath));

      String line;

      while((line = inputs.readLine()) != null)

        add(line.trim());

    } catch(IOException e) {

      throw new RuntimeException(e);

    }

  }

} ///:~

This StringList only holds Objects, just as an ArrayList does, so we need an adapter to turn the Strings into MouseActions:

//: statemachine:mouse:MouseMoveList.java

// A "transformer" to produce a

// List of MouseAction objects.

package statemachine.mouse;

import java.util.*;

import com.bruceeckel.util.*;

 

public class MouseMoveList extends ArrayList {

  public MouseMoveList(Iterator it) {

    while(it.hasNext())

      add(MouseAction.forString((String)it.next()));

  }

} ///:~

 

The MouseMoveList looks a bit like a decorator, and acts a bit like an adapter. However, an adapter changes one interface to another, and a decorator adds functionality or data. MouseMoveList changes the contents of the container, so it might be thought of as a Transformer.

With these tools in place, it’s now possible to create the first version of the mousetrap program. Each State subclass defines it’s run( ) behavior, and also establishes its next state with an if-else clause:

//: statemachine:mousetrap1:MouseTrapTest.java

// State Machine pattern using 'if' statements

// to determine the next state.

package statemachine.mousetrap1;

import statemachine.mouse.*;

import statemachine.*;

import com.bruceeckel.util.*;

import java.util.*;

import java.io.*;

import junit.framework.*;

 

// A different subclass for each state:

 

class Waiting implements State {

  public void run() {

    System.out.println(

      "Waiting: Broadcasting cheese smell");

  }

  public State next(Input i) {

    MouseAction ma = (MouseAction)i;

    if(ma.equals(MouseAction.appears))

      return MouseTrap.lurin