PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1
CHAPTER 10 ■ PATTERNS FOR FLEXIBLE OBJECT PROGRAMMING

and queries transparent to the client. Trees are easy to traverse (as we shall see in the next chapter). It is
easy to add new component types to Composite structures.
On the downside, Composites rely on the similarity of their parts. As soon as we introduce complex
rules as to which composite object can hold which set of components, our code can become hard to
manage. Composites do not lend themselves well to storage in relational databases but are well suited to
XML persistence.


The Decorator Pattern


While the Composite pattern helps us to create a flexible representation of aggregated components, the
Decorator pattern uses a similar structure to help us to modify the functionality of concrete
components. Once again, the key to this pattern lies in the importance of composition at runtime.
Inheritance is a neat way of building on characteristics laid down by a parent class. This neatness can
lead you to hard-code variation into your inheritance hierarchies, often causing inflexibility.


The Problem


Building all your functionality into an inheritance structure can result in an explosion of classes in a
system. Even worse, as you try to apply similar modifications to different branches of your inheritance
tree, you are likely to see duplication emerge.
Let’s return to our game. Here, I define a Tile class and a derived type:


abstract class Tile {
abstract function getWealthFactor();
}


class Plains extends Tile {
private $wealthfactor = 2;
function getWealthFactor() {
return $this->wealthfactor;
}
}


I define a Tile class. This represents a square on which my units might be found. Each tile has
certain characteristics. In this example, I have defined a getWealthFactor() method that affects the
revenue a particular square might generate if owned by a player. As you can see, Plains objects have a
wealth factor of 2. Obviously, tiles manage other data. They might also hold a reference to image
information so that the board could be drawn. Once again, I’ll keep things simple here.
I need to modify the behavior of the Plains object to handle the effects of natural resources and
human abuse. I wish to model the occurrence of diamonds on the landscape, and the damage caused by
pollution. One approach might be to inherit from the Plains object:


class DiamondPlains extends Plains {
function getWealthFactor() {
return parent::getWealthFactor() + 2;
}
}


class PollutedPlains extends Plains {
function getWealthFactor() {
return parent::getWealthFactor() - 4;
}
}

Free download pdf