1.4 The Union and Composite Patterns
Keywords: current

Next: 1.4.1 Member Hoisting Up: 1. From C++ to Previous: 1.3.4 Printing Objects

#
1.4 The Union and Composite Patterns

In our department directory example, an object of type `Entry` only has one form, namely an instance of class `Entry`. If we were designing the data for a more comprehensive directory such as a city phone directory, we would need more than one form of entry. At a minimum, we would need entry formats suitable for business listings, government listings, and residential listings. For such a phone directory, we might define an entry as follows.

A `CityEntry` is either:

- a `BusinessEntry(name,addr,phone,city,state)`,
- a `GovernmentEntry(name,addr,phone,city,state,gov)`, or
- a `ResidentialEntry(name,addr,phone)`,

where `name` is a string specifying the name for the listing, `addr` is a string specifying the street address for the listing, `phone` is a string specifying the phone number (with area code) for the listing, `city` and `state` are strings specifying the city and state for the listing, and `gov` is a string specifying the government entity for that the listing, e.g. the "City of Houston".

The `BusinessEntry` and `GovernmentEntry` forms include city and state information because businesses and government agencies that serve clients in cities outside their local calling area often elect to have their phone numbers included in the directories of other cities (in addition to the cities where they are located). In addition, government listings include a string specifying the government entity to which they belong. For example, a listing for the Federal Bureau of Investigation would specify the "U.S. Government" as the `gov` field.

In Java, we can define the `CityEntry` type by introducing a ``dummy'' `CityEntry` class that we extend by ``concrete'' classes1.1 for each different form of `Entry` data. This technique, which is widely used in object-oriented programming, is called the union pattern. In the union pattern, an abstract class serves as the root of a hierarchy of subclasses called variants, which are the component types of the union. In this example, there are three variant classes: `BusinessEntry`, `GovernmentEntry`, `ResidentialEntry`. The following Java code defines the city-entry type:

Figure 1.1: The `City Directory` union class hierarchy

The Java code in the `CityEntry` example above involves several concepts that we have not discussed before.

- The attribute `abstract` attached to the class `CityEntry` indicates that `CityEntry` is a class that cannot be instantiated. The class `CityEntry` exists solely to group the concrete classes `BusinessEntry`, `GovernmentEntry`, and `ResidentialEntry` as a type that includes all three kinds of data.
- The concrete classes `BusinessEntry`, `GovernmentEntry`, and `ResidentialEntry` are the only subclasses of the class `CityEntry`. Hence, the only values of type `CityEntry` are the instances of the classes `BusinessEntry`, `GovernmentEntry`, and `ResidentialEntry`.
- Each concrete class includes a constructor definition that specifies how new instances of the class are initialized. Each concrete class also includes getter (accessor) methods (like `getPhone`) to get the values of the various fields of the class.

The following expression creates a `BusinessEntry` for Rice University

    new BusinessEntry("Rice University", "6100 Main Street",
    "713-348-8101", "Houston", "Texas")

This syntax is wordy but straightforward. Don't forget to include the keyword `new` at the front on each constructor invocation!

Finger Exercise Enter the preceding class definitions into the Definitions pane of DrJava. Compile this program and evaluate the following expressions in the Interactions pane:

    BusinessEntry e1 = new BusinessEntry("Rice University", "6100 Main St.",
      "713-527-8101", "Houston", "TX");
    ResidentialEntry e2 = new ResidentialEntry("Robert Cartwright",
      "3310 Underwood St.", "713-660-0967");
    e1.getName()
    e2.getName()

Did you get the results that you expected?

Subsections

- 1.4.1 Member Hoisting
- 1.4.2 The Composite Pattern
- 1.4.3 Defining Instance Methods for a Composite Class
- 1.4.4 Conditional Statements
- 1.4.5 Blocks
- 1.4.6 Singleton Pattern

Next: 1.4.1 Member Hoisting Up: 1. From C++ to Previous: 1.3.4 Printing Objects