Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Design patterns, the big picture, Part 2: Gang-of-four classics revisited

Learn the GoF design patterns in Java code, starting with Strategy and Visitor

  • Print
  • Feedback

Page 2 of 4

Listing 4. Context is configured with a ConcreteStrategyx instance

class Context
{
   private Strategy strategy;

   public Context(Strategy strategy)
   {
      setStrategy(strategy);
   }

   public void executeStrategy(int x)
   {
      strategy.execute(x);
   }

   public void setStrategy(Strategy strategy)
   {
      this.strategy = strategy;
   }
}

The Context class in Listing 4 stores a strategy when it is created, provides a method to subsequently change the strategy, and provides another method to execute the current strategy. Except for passing a strategy to the constructor, this pattern can be seen in the java.awt .Container class, whose void setLayout(LayoutManager mgr) and void doLayout() methods specify and execute the layout manager strategy.

StrategyDemo

We need a client to demonstrate the previous types. Listing 5 presents a StrategyDemo client class.

Listing 5. StrategyDemo

public class StrategyDemo
{
   public static void main(String[] args)
   {
      Context context = new Context(new ConcreteStrategyA());
      context.executeStrategy(1);
      context.setStrategy(new ConcreteStrategyB());
      context.executeStrategy(2);
   }
}

A concrete strategy is associated with a Context instance when the context is created. The strategy can be subsequently changed via a context method call.

If you compile these classes and run StrategyDemo, you should observe the following output:

executing strategy A: x = 1
executing strategy B: x = 2

 

Revisiting the Visitor pattern

Visitor is the final software design pattern to appear in Design Patterns. Although this behavioral pattern is presented last in the book for alphabetical reasons, some believe that it should come last due to its complexity. Newcomers to Visitor often struggle with this software design pattern.

As explained in Design Patterns, a visitor lets you add operations to classes without changing them, a bit of magic that is facilitated by the so-called double dispatch technique. In order to understand the Visitor pattern, we need first to digest double dispatch.

 

What is double dispatch?

Java and many other languages support polymorphism (many shapes) via a technique known as dynamic dispatch, in which a message is mapped to a specific sequence of code at runtime. Dynamic dispatch is classified as either single dispatch or multiple dispatch:

  • Single dispatch: Given a class hierarchy where each class implements the same method (that is, each subclass overrides the previous class's version of the method), and given a variable that's assigned an instance of one of these classes, the type can be figured out only at runtime. For example, suppose each class implements method print(). Suppose too that one of these classes is instantiated at runtime and its variable assigned to variable a. When the Java compiler encounters a.print();, it can only verify that a's type contains a print() method. It doesn't know which method to call. At runtime, the virtual machine examines the reference in variable a and figures out the actual type in order to call the right method. This situation, in which an implementation is based on a single type (the type of the instance), is known as single dispatch.
  • Multiple dispatch: Unlike in single dispatch, where a single argument determines which method of that name to invoke, multiple dispatch uses all of its arguments. In other words, it generalizes dynamic dispatch to work with two or more objects. (Note that the argument in single dispatch is typically specified with a period separator to the left of the method name being called, such as the a in a.print().)

Finally, double dispatch is a special case of multiple dispatch in which the runtime types of two objects are involved in the call. Although Java supports single dispatch, it doesn't support double dispatch directly. But we can simulate it.

  • Print
  • Feedback

Resources

David Geary's Java design patterns series on JavaWorld: Learn more of the Gang of Four patterns in Java code: