PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 9 ■ GENERATING OBJECTS


class Sea {}
class EarthSea extends Sea {}
class MarsSea extends Sea {}


class Plains {}
class EarthPlains extends Plains {}
class MarsPlains extends Plains {}


class Forest {}
class EarthForest extends Forest {}
class MarsForest extends Forest {}


class TerrainFactory {
private $sea;
private $forest;
private $plains;


function __construct( Sea $sea, Plains $plains, Forest $forest ) {
$this->sea = $sea;
$this->plains = $plains;
$this->forest = $forest;
}


function getSea( ) {
return clone $this->sea;
}


function getPlains( ) {
return clone $this->plains;
}


function getForest( ) {
return clone $this->forest;
}
}


$factory = new TerrainFactory( new EarthSea(),
new EarthPlains(),
new EarthForest() );
print_r( $factory->getSea() );
print_r( $factory->getPlains() );
print_r( $factory->getForest() );


As you can see, I load up a concrete TerrainFactory with instances of product objects. When a client
calls getSea(), I return a clone of the Sea object that I cached during initialization. Not only have I saved
a couple of classes but I have bought additional flexibility. Want to play a game on a new planet with
Earth-like seas and forests, but Mars-like plains? No need to write a new creator class—you can simply
change the mix of classes you add to TerrainFactory:


$factory = new TerrainFactory( new EarthSea(),
new MarsPlains(),
new EarthForest() );


So the Prototype pattern allows you to take advantage of the flexibility afforded by composition. We
get more than that, though. Because you are storing and cloning objects at runtime, you reproduce

Free download pdf