PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1
CHAPTER 9 ■ GENERATING OBJECTS

The Problem


Imagine a Civilization-style web game in which units operate on a grid of tiles. Each tile can represent
sea, plains, or forests. The terrain type constrains the movement and combat abilities of units occupying
the tile. You might have a TerrainFactory object that serves up Sea, Forest, and Plains objects. You
decide that you will allow the user to choose among radically different environments, so the Sea object is
an abstract superclass implemented by MarsSea and EarthSea. Forest and Plains objects are similarly
implemented. The forces here lend themselves to the Abstract Factory pattern. You have distinct
product hierarchies (Sea, Plains, Forests), with strong family relationships cutting across inheritance
(Earth, Mars). Figure 9-10 presents a class diagram that shows how you might deploy the Abstract
Factory and Factory Method patterns to work with these products.
As you can see, I rely on inheritance to group the terrain family for the products that a factory will
generate. This is a workable solution, but it requires a large inheritance hierarchy, and it is relatively
inflexible. When you do not want parallel inheritance hierarchies, and when you need to maximize
runtime flexibility, the Prototype pattern can be used in a powerful variation on the Abstract Factory
pattern.


Figure 9-10. Handling terrains with the Abstract Factory method


Implementation


When you work with the Abstract Factory/Factory Method patterns, you must decide, at some point, which
concrete creator we wish to work with, probably by checking some kind of preference flag. Since you must
do this anyway, why not simply create a factory class that stores concrete products, and populate this
during initialization? You can cut down on a couple of classes this way and, as you shall see, take advantage
of other benefits. Here’s some simple code that uses the Prototype pattern in a factory:

Free download pdf