PHP Objects, Patterns and Practice (3rd edition)

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

Consequences


Like the Composite pattern, Decorator can be confusing. It is important to remember that both
composition and inheritance are coming into play at the same time. So LogRequest inherits its interface
from ProcessRequest, but it is acting as a wrapper around another ProcessRequest object.
Because a decorator object forms a wrapper around a child object, it helps to keep the interface as
sparse as possible. If you build a heavily featured base class, then decorators are forced to delegate to all
public methods in their contained object. This can be done in the abstract decorator class but still
introduces the kind of coupling that can lead to bugs.
Some programmers create decorators that do not share a common type with the objects they
modify. As long as they fulfill the same interface as these objects, this strategy can work well. You get the
benefit of being able to use the built-in interceptor methods to automate delegation (implementing
__call() to catch calls to nonexistent methods and invoking the same method on the child object
automatically). However, by doing this you also lose the safety afforded by class type checking. In our
examples so far, client code can demand a Tile or a ProcessRequest object in its argument list and be
certain of its interface, whether or not the object in question is heavily decorated.


The Facade Pattern


You may have had occasion to stitch third-party systems into your own projects in the past. Whether or
not the code is object oriented, it will often be daunting, large, and complex. Your own code, too, may
become a challenge to the client programmer who needs only to access a few features. The Facade
pattern is a way of providing a simple, clear interface to complex systems.


The Problem


Systems tend to evolve large amounts of code that is really only useful within the system itself. Just as
classes define clear public interfaces and hide their guts away from the rest of the world, so should well-
designed systems. However, it is not always clear which parts of a system are designed to be used by
client code and which are best hidden.
As you work with subsystems (like web forums or gallery applications), you may find yourself
making calls deep into the logic of the code. If the subsystem code is subject to change over time, and
your code interacts with it at many different points, you may find yourself with a serious maintenance
problem as the subsystem evolves.
Similarly, when you build your own systems, it is a good idea to organize distinct parts into separate
tiers. Typically, you may have a tier responsible for application logic, another for database interaction,
another for presentation, and so on. You should aspire to keep these tiers as independent of one another
as you can, so that a change in one area of your project will have minimal repercussions elsewhere. If
code from one tier is tightly integrated into code from another, then this objective is hard to meet.
Here is some deliberately confusing procedural code that makes a song-and-dance routine of the
simple process of getting log information from a file and turning it into object data:


function getProductFileLines( $file ) {
return file( $file );
}


function getProductObjectFromId( $id, $productname ) {
// some kind of database lookup
return new Product( $id, $productname );
}

Free download pdf