CHAPTER 9 ■ GENERATING OBJECTS
The Problem
Imagine a personal organizer project. Among others, you manage Appointment objects. Your business
group has forged a relationship with another company, and you must communicate appointment data
to them using a format called BloggsCal. The business group warns you that you may face yet more
formats as time wears on, though.
Staying at the level of interface alone, you can identify two participants right away. You need a
data encoder that converts your Appointment objects into a proprietary format. Let’s call that class
ApptEncoder. You need a manager class that will retrieve an encoder and maybe work with it to
communicate with a third party. You might call that CommsManager. Using the terminology of the
pattern, the CommsManager is the creator, and the ApptEncoder is the product. You can see this structure
in Figure 9-3.
Figure 9-3. Abstract creator and product classes
How do you get your hands on a real concrete ApptEncoder, though?
You could demand that an ApptEncoder is passed to the CommsManager, but that simply defers your
problem, and you want the buck to stop about here. Here I instantiate a BloggsApptEncoder object
directly within the CommsManager class:
abstract class ApptEncoder {
abstract function encode();
}
class BloggsApptEncoder extends ApptEncoder {
function encode() {
return "Appointment data encoded in BloggsCal format\n";
}
}
class MegaApptEncoder extends ApptEncoder {
function encode() {
return "Appointment data encoded in MegaCal format\n";
}
}
class CommsManager {
function getApptEncoder() {
return new BloggsApptEncoder();
}
}
The CommsManager class is responsible for generating BloggsApptEncoder objects. When the sands of
corporate allegiance inevitably shift and we are asked to convert our system to work with a new format
called MegaCal, we can simply add a conditional into the CommsManager::getApptEncoder() method. This
is the strategy we have used in the past, after all. Let’s build a new implementation of CommsManager that
handles both BloggsCal and MegaCal formats:
class CommsManager {
const BLOGGS = 1;