CMPT 300 Design Patterns
May 2008

Lab 5 - The Adapter & Facade Patterns


<< lab5.zip >>

Adapter Pattern


The Adapter pattern "coverts the interface of a class into another interface that clients expect. The Adapter pattern allows classes work together that otherwise could not because of incompatible interfaces."

In UML, it appears as

Adapter Pattern

An Example

- Target.java

- Adapter.java

- Adaptee.java

- TestAdapter.java


A More Interesting Example

At first, a simple swing program:

- PlanetClientNoAdapter.java

This program uses a JFrame which expects JComponents.

Now, suppose you have the following Icon

- PlanetIcon.java

It draws planets.

The client is a JFrame which expects JComponents, not Icon objects.

We can adapt the PlanetIcon using the following adapter:

- IconAdapter.java

It is important to note that an IconAdapter IS-A JComponent!

The client using this adapter:

- PlanetClient.java

In UML

Adapter Pattern


The Adapter Lab

Way back in the days of Java 1.0, there was an Enumeration interface.

An example:

- EnumerateTest.java

Beginning with Java 1.2, using an Iterator was recommended over Enumeration.

An iteration works as follows:

- IterateTest.java

However, old legacy code may still provide an Enumeration instead of an Iterator.

Consider the the API for OldStyleList:


Method Signature
What It Does
public OldStyleList(); Creates an OldStyleList
public boolean add(Object e) Adds Object e to the list
public Enumeration elements() Returns an Enumeration of the elements in the list

Now consider if client code wishes to use an Iterator - not an Enumeration - with OldStyleList. It cannot as OldStyleList only provides an Enumeration. The solution -> an Adapter!

In UML, we wish to accomplish the following:

Adapter Pattern

Part I

Write the EnumerationAdapter class so that a client can get an Iterator for an OldStyleList. That is, adapt the Enumerator so that it acts as an Iterator.

To test your adapter, modify IterateTest.java so that it works with an OldStyleList (instead of a Vector.)

Part II

OK, the OldStyleList class doesn't really exist in the API; we made it up for this exercise. However, the ArrayList class does exist and only provides an Iterator (via the iterator() method it inherits from the AbstractList class.) Write an IterationAdapter that does just the opposite of what you completed in Part I. That is, it adapts an iterator to an enumeration. Write some test code that allows you to insert several items into an ArrayList and then perform an enumeration of these items.



The Facade Pattern

The Facade pattern addresses the need where we need to simplify the interface to an existing system.

Consider if we have the situation whereby a client must interface with a database, a model, and some elements.

The client must first open the database to get a model. It must then query the model to get an element. Lastly, it must use the element to get information from  the database. In UML, this appears as:



If we introduce the Facade, this now appears as:



Consider a system where we wanted to make some tea. This system may have the following objects:



The code:

- TeaCup.java

- Tea.java

- TeaInfuser.java

- Water.java

To make tea requires the following code:

TeaCup blueCup = new TeaCup();
Water water = new Water();
TeaInfuser infuser = new TeaInfuser();
Tea tea = new Tea("Earl Grey");

infuser.addTea(tea);
       
water.boilWater();
       
blueCup.addWater(water);
       
blueCup.setSteepTime(15);
       
blueCup.steep();


More complete code:

- MakeTea.java


This is where the facade pattern can come in useful

Part III

Write a class called TeaFacade.java

This class will have a constructor with the following signature:

public TeaFacade(TeaCup cup, Water water, TeaInfuser infuser)

It will also provide the following method that makes tea:

public void makeTea(String teaType)

This method is passed a string with the name of the tea to make.


Now, rather than the client use the code shown above to make tea, it now just has  to do the following:

TeaFacade teaMaker = new TeaFacade(blueCup,water,infuser);
teaMaker.makeTea("Earl Grey");


Modify so that it now makes tea using the TeaFacade.

>> It is important to note that the facade pattern is not a demo program, rather, the facade that is created to simplify the interface to a system becomes part of the API of the system. <<.

Executors

Notice how the system has to wait for the water to boil before is adds tea to the infuser? We could have these activities performed in parallel using an executor. An executor allows multiple tasks to be run in parallel. Executors can be created with the following code:

import java.util.concurrent.*;

ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(/** a Runnable task **/);

We must pass the service a task  that implements the Runnable interface.

This can be done with an anonymous inner class, such as the following

service.execute(new Runnable() { public void run() { infuser.addTea(tea); }  });

This allows the statement infuser.addTea(tea); to be performed in parallel with other statements in the program.

Part IV

First modify MakeTeaInParallel.java so that it uses the executor to run addTea() in an executor. Once you get this working, modify your version of MakeTea.java that uses TeaFacade so that you invoke addTea() using the executor.

Threads?

For those of you familiar with threads, executors sound awfully familiar. They are indeed, but with a much richer concurrency library.


Before we conclude with executors (for now), it is interesting to note the Executors practices a pattern we have recently seen. What pattern?