Let's consider our model of a department directory. Fundamentally, we said that
A DeptDirectory is either:
- an empty directory, Empty, or
- a non-empty directory Cons, which has
- a first, which is an Entry (the "first" entry in the directory), and
- a rest, which is a DeptDirectory (the "rest" of the directory)
In OO design, the goal is to express the problem, not to contrive a process to get the right answer. Proper abstract modeling of the problem space will automatically lead to correct results.
Thus we create the following classes and relationships (DeptDirectory.java):

We clearly see the Union pattern here, as DeptDirectory is an abstraction of both Empty and Cons. But the unique characteristic is that Cons, a subclass of DeptDirectory, contains a reference to ("is composed with" --"has-a") its own superclass. That is, Cons is self-referential. This is also known as a recursive data structure.
DeptDirectory is an example of the classic list data structure, which enables us to represent arbitrarily large data sets.
This recursive data structure is so common, it can be expressed as the Composite Design Pattern.
Now, our data structure so far is nice, but it would be even nicer if we could actually do something with it...
But since we are doing OOP, we must be driven by abstraction. The question to ask is: "Fundamentally, what can a DeptDirectory do?" or "Fundamentally, how does a DeptDirectory behave?"
One possible answer is: "One should be able to ask a DeptDirectory to find the address associated with a given name."
Note that this is quite different that asking "How can I get my data structure to do such and such?" If we model our system correctly, it will automatically and intrinsically do what we need it to do.
Our question and answer above have a couple of implications:
What are the concrete behaviors of Empty and Cons?
This is OOP, so if that what we mean, then that's what we'll code (DeptDirectory2.java):

The actual code looks like this (the relevant code here is in red):
abstract class DeptDirectory {
public abstract String findAddress(String aName);
}
class Empty extends DeptDirectory {
public String findAddress(String aName) {
return (null);
}
}
class Cons extends DeptDirectory {
Entry first;
DeptDirectory rest;
/* constructor */
Cons(Entry f, DeptDirectory r) {
this.first = f;
this.rest = r;
}
/* accessors */
Entry getFirst() { return this.first; }
DeptDirectory getRest() { return this.rest; }
public String findAddress(String aName) {
if(first.getName().equals(aName)) {
return first.getAddress();
}
else {
return rest.findAddress(aName);
}
}
}
The code is exactly what we said it had to be, before we wrote any code. No more, no less.
So how would you use/test this code? Try the following in DrJava (you will need to open Entry.java too):
| Interactions pane input | Result |
|
DeptDirectory d0 = new Empty(); d0.findAddress("anyone") |
null |
|
DeptDirectory d1 = new Cons(new Entry("Bilbo Baggins", "The Shire", "314-1592"), d0); d1.findAddress("Bilbo Baggins") d1.findAddress("Frodo") |
"The Shire" null |
|
DeptDirectory d2 = new Cons( new Entry("Gollum", "Misty Mountains", "666-6666"), d1); d2.findAddress("Bilbo Baggins") d2.findAddress("Gollum") d2.findAddress("Gandalf") |
"The Shire" "Misty Mountains" null |