Design Patterns: Bridge, Decorator, Chain of Responsibility, Interpreter, Visitor

Bridge Outline for Lecture 26 [HFDP, §14.1] Now, let’s look at the class I. Bridge diagram for the (for example, at II. Decorator http://www.exciton.cs.rice.edu/JAvaResources/DesignPatterns/StatePat.htm ). III. Chain of Note that the Context object holds a Responsibility reference to an abstract class. This is the IV. Interpreter abstract class from which the concrete states V. Visitor are derived.

It turns out that the same structure is valuable for implementing drivers. What’s a driver?

Drivers are generally used by various applications. Consider a printer driver, for example. There is a driver for a particular printer for each OS. Many different applications can use that printer, providing that the right driver is present.

This is an example of the bridge pattern. We have various abstractions (the applications) and various implementations (the drivers). If the applications aren’t in a hierarchy, the for Bridge is exactly the same as the class diagram for State.

But often, the abstractions are in a hierarchy. HFDP gives the example of televisions and remotes. TVs have behavior in common, and so do remotes. If they’re “universal remotes,” they can be used by lots of different kinds of TVs.

This leads to the UML diagram on p. 613 of HFDP , or view it online .

What are the advantages of Bridge?

OK, we just told you the right way to handle this problem. What would be the wrong way? Can you imagine using a lot more

Lecture 26 Object-Oriented Languages and Systems 1 subclasses?

So one way of looking at Bridge is that it avoids unnecessary subclassing.

Decorator [HFDP, Ch. 3] Is too much subclassing a good thing? Why not?

HFDP has a good example on p. 80. Here, a separate subclass is created for each combination of coffee and condiments.

There are four types of coffee:

• HouseBlend • DarkRoast • Decaf • Espresso

There are many condiments, e.g., milk, soy, mocha, whip.

Each subclass has only one method. What is it?

Attempt #2: Let’s use a separate instance variable for each condiment … along with setters and getters, of course.

How should we implement cost ()? In the superclass or subclases?

This is better, but still not ideal. Why?

CSC/ECE 517 Lecture Notes © 2007 Edward F. Gehringer 2

What principle have we violated?

How can we solve this problem without using inheritance?

We will just have the with-condiments versions of our object the original version.

Look at the diagram on p. 89. We start out with a cost for DarkRoast coffee.

Then if we want the cost of DarkRoast with Mocha, we give Mocha a method.

Mocha’s method calls the a method of Beverage.

In order to do this, Beverage and Mocha should both the same .

Now, we can do the same for all the other components. They will all have cost () methods. (How should this method be implemented?)

Suppose we have more than one condiment per beverage? We can wrap one component in another.

Now let’s take a look at the class diagram .

Another nice thing about Decorator: You can add functionality at any time without disturbing the base object!

Let’s think of some other uses of Decorator.

Lecture 26 Object-Oriented Languages and Systems 3

Chain of Responsibility [HFDP, §14.3] You know how filters in Unix are so powerful? Take this one , for example: grep "execute(" `find mydir -name "*.java"` | awk -F: '{print }' | sort -u | wc -l

It prints the number of files in mydir that

What happens? At each step, a request is passed along from one handler to the next.

Each handler can modify the request, by processing what it can, and then pass the request to the next handler.

The example in HFDP is for various e-mail handlers that route messages to various mailboxes depending on the subject.

Let’s take a look at the class diagram .

What are some other examples of Chain of Responsibility?

Interpeter [HFDP, §14.5] We all know the general idea of an interpreter: Read commands, and do what they say.

The example in HFDP is a duck, which can do one of three things:

• Fly • Quack • Turn right

One program for the interpreter is just …

right; while (daylight) fly; quack;

An interpreter always has some notion of compound commands, or repetition.

CSC/ECE 517 Lecture Notes © 2007 Edward F. Gehringer 4

Let’s take a look at the class diagram of this interpreter, from p. 621, and the generalized class diagram .

Can you think of some other examples?

Visitor [HFDP, §14.9] Remember our discussion of overloading vs. overriding, from Lecture 16 and §2.8 of Skrien? At that time, we said,

In summary, the compiler decides which overloaded method to call by looking at the declared type of • the object being sent the message and • the declared types of the arguments to the method call. The method is chosen at runtime by dynamic method invocation using the actual value of the object being sent the message. The actual classes of the arguments to the method call do not play a role. This is very different from a language like CLOS, which uses the actual types of the arguments to decide which method to execute.

Suppose we did want the classes of the arguments to be used to determine which method to call.

My favorite example is “double-dispatching” in arithmetic expressions.

• If you add an integer and a floating-point number, what type should the result be?

• Assuming you have a Fraction class, if you add an integer and a fraction, what type should the result be?

• If you add a floating-point number and a complex number, what type should the result be?

Should either the floating-point or complex number be able to be the receiver? Should either be able to be the argument?

Lecture 26 Object-Oriented Languages and Systems 5

So, the method called should depend both on the class of the receiver and the class of the argument. How do we achieve this effect?

Let’s say that we implement the Sum method in all numeric classes—Integer, Floating Point, Fraction, and Complex.

So, if we’re performing an addition, we invoke the Sum method of the class.

Now, this Sum method knows that what it does actually depends on the class of its argument. How does it achieve this effect?

This method, e.g., in the Complex class, is called something like, SumFromFloatingPoint.

• What does it do?

• What does it return?

OK, suppose that we have the four numeric classes mentioned above. How many Sum… methods do we need altogether?

What’s the example given in the text for Visitor? Can you explain it?

CSC/ECE 517 Lecture Notes © 2007 Edward F. Gehringer 6