PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 9 ■ GENERATING OBJECTS


abstract class CommsManager {
const APPT = 1;
const TTD = 2;
const CONTACT = 3;
abstract function getHeaderText();
abstract function make( $flag_int );
abstract function getFooterText();
}


class BloggsCommsManager extends CommsManager {
function getHeaderText() {
return "BloggsCal header\n";
}
function make( $flag_int ) {
switch ( $flag_int ) {
case self::APPT:
return new BloggsApptEncoder();
case self::CONTACT:
return new BloggsContactEncoder();
case self::TTD:
return new BloggsTtdEncoder();
}
}


function getFooterText() {
return "BloggsCal footer\n";
}
}


As you can see, I have made the class interface more compact. I've done this at a considerable cost,
though. In using a factory method, you define a clear interface and force all concrete factory objects to
honor it. In using a single make() method, I must remember to support all product objects in all the
concrete creators. I also introduce parallel conditionals, as each concrete creator must implement the
same flag tests. A client class cannot be certain that concrete creators generate all the products because
the internals of make() are a matter of choice in each case.
On the other hand, you can build more flexible creators. The base creator class can provide a make()
method that guarantees a default implementation of each product family. Concrete children could then
modify this behavior selectively. It would be up to implementing creator classes to call the default make()
method after providing their own implementation.
You will see another variation on the Abstract Factory pattern in the next section.


Prototype


The emergence of parallel inheritance hierarchies can be a problem with the Factory Method pattern.
This is a kind of coupling that makes some programmers uncomfortable. Every time you add a product
family, you are forced to create an associated concrete creator (the BloggsCal encoders are matched by
BloggsCommsManager, for example). In a system that grows fast to encompass many products,
maintaining this kind of relationship can quickly become tiresome.
One way of avoiding this dependency is to use PHP’s clone keyword to duplicate existing concrete
products. The concrete product classes themselves then become the basis of their own generation. This
is the Prototype pattern. It enables you to replace inheritance with composition. This in turn promotes
runtime flexibility and reduces the number of classes you must create.

Free download pdf