Object Oriented Design Patterns for PHPPresentation Transcript
Object Oriented Design Patterns for PHP <?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?> An introduction of sorts into the world of design patterns for object oriented PHP, as brought to you by Robert Gonzalez. http://www.robert-gonzalez.com [email_address] http://www.robert-gonzalez.com/personal/meetups/apache-49-20081218-code.tar.gz http://www.robert-gonzalez.com/personal/meetups/apache-49-20081218-presentation.odp http://www.slideshare.net/RobertGonzalez/object-oriented-design-patterns-for-php-presentation/
Object Oriented Design Patterns for PHP
Who is this Robert dude?
What are design patterns?
How can design patterns help you?
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?> $this->setup();
Object Oriented Design Patterns for PHP
Who is this Robert dude?
Husband and father
Web developer
Self taught
Began learning HTML in 1997
Began learning Perl in 2000
Began learning PHP in 2003
Full time developer for Bay Alarm Company since 2006
PHP freak
Administrator of the PHP Developers Network forums
Frequent contributor to Professional PHP Google group
Chief helper of n00Bs (at work and beyond)
Zend Certified PHP 5 Engineer
Awesome barbecuer
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
What are design patterns?
The words ”Object Oriented Design” repeated on wall paper
An industry buzzword that gets you into meetups
Recurring solutions to common software development challenges
Mind bending algorithms of confusion and indigestion
The words ”Object Oriented Design” repeated on wall paper
An industry buzzword that gets you into meetups
Recurring solutions to common software development challenges
Mind bending algorithms of confusion and indigestion
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
What are design patterns not ?
They are not the end all, be all to all of your coding challenges.
They are not a requirement of object oriented programming.
They are not a requirement of good programming.
They are not a substitute for application code and logic.
They are not always the best solution for the job.
They are not always the easiest concept to grasp and/or use.
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
Some common software development challenges:
Building new applications while leveraging existing codebases
Building/enhancing applications securely, quickly and effectively
Integrating new and existing applications
Multiple developers programming the same product
Few developers programming many products
Varying, sometimes unknown, data sources
Varying, sometimes unknown, operating systems
Varying, sometimes unknown, platforms and setups
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
Yeah, this is all well and good. And your presentation so far kicks all kinds of ass, but seriously, what are design patterns really going to do for me?
Let's have a look at some patterns and see ...
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Lazy Load Pattern
Lazy loading is the process of delaying the instantiation of an object until the instance is needed.
We all know the mantra, lazy programmers are the best programmers.
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Lazy Load Pattern
<?php /** * Sample class */ class MyClass { /** * Holder for the SomeObject object * * @access protected * @var SomeObject */ protected $_myobject = null ; /** * Get the instance of SomeObject, but only when we need it * * @access public * @return SomeObject */ public function fetchObject () { if ( $this -> _myobject === null ) { $this -> _myobject = new SomeObject ; } return $this -> _myobject ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
Why the Lazy Load rocks:
Delays resource consumption until it is needed, which may be never
Is relatively easy to understand
Offers an encapsulated means of creating objects
Offers an encapsulated means of storing objects for use later
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Did you just see that? Did he just say storing objects for use later?
Object Oriented Design Patterns for PHP
The Registry Pattern
A registry is an object that other objects can use to access data, settings, values and other objects from a sort of internal storehouse.
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Registry Pattern
<?php /** * Class that manages registry entries for an application. */ class Registry { /** * Holds the registry labels and values data */ protected static $_register = array(); /** * Sets a value into the registry if there is no value with this label already */ public static function set ( $label , $value ) { if (!isset( self :: $_register [ $label ])) { self :: $_register [ $label ] = $value ; } } /** * Gets a value from the registry if there is a label with this value */ public static function get ( $label ) { if (isset( self :: $_register [ $label ]) { return self :: $_register [ $label ]; } } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
Common uses of a Registry:
Maintaining values throughout a request
Setting/getting configuration values
Allowing access to variables within an application without globals
For Windows user, causing hours and hours of grief when corrupt
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Can you think of a feature/extension of PHP that uses a sort of registry pattern?
Is there way to instantiate the Registry Pattern but force only a single instance of it?
Object Oriented Design Patterns for PHP
The Singleton Pattern
The singleton patterns ensures that one and only one instance of an object exists.
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Singleton Pattern
<?php /** * Class that only ever has one instance of itself floating around. */ class Singleton { /** * Holds the instance of itself in this property */ private static $_instance = null ; /** * Final and private constructor means this can only be instantiated from within */ final private function __construct () {} /** * Gets the single instance of this object */ public static function getInstance () { if ( self :: $_instance === null ) { self :: $_instance = new self ; } return self :: $_instance ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
Pros and cons of the Singleton:
Pro: You know you have the same instance available at all times.
Con: One and only one instance is all you get.
Pro: Instantiates itself for you so all you need to do is get it.
Con: Autoinstantiation diminishes flexibility of argument passing.
Pro: Since it is singleton it can replace global variable declaration.
Con: Since it is singleton it can replace global variable declaration.
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
What are some situations of a developer needing one and only one instance of an object?
Object Oriented Design Patterns for PHP
The Factory Method Pattern
The factory method is a method whose sole purpose in life is to create objects. Most commonly (and really per definition) the factory method is an interface method that delegates object instantiation decisions to subclasses. However, it also commonly acceptable to say that a method that creates objects (both of known and unknown classes) is a factory method.
PLEASE NOTE: The factory method pattern is not the same as the factory pattern, which we will NOT be covering in this presentation.
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Factory Method Pattern
<?php /** * A factory method implementation */ abstract class Creator { /** * Abstract factory method to be defined by child classes */ abstract public function createObject ( $type ); } class ConcreteCreatorA extends Creator { public function createObject ( $type ) { switch ( $type ) { // Handle cases for concrete classes } } } class ConcreteCreatorB extends Creator { public function createObject ( $type ) { switch ( $type ) { // Handle cases for concrete classes } } } $b = new ConcreteCreatorB ; $b -> create ( 'ConcreteProductB' );
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Factory Method Pattern, an alternative
<?php /** * A little class to handle creation of objects */ class Lib_Factory { /** * Create an object of type $name */ public static function createObject ( $name , $args = array()) { /** * Move our class name into a file path, turning names like * App_Db_Handler into something like App/Db/Handler.php */ $file = str_replace ( '_' , PATH_SEPARATOR , $name ) . '.php' ; // Get the file if ( file_exists ( $file )) { require_once $file ; $obj = new $name ( $args ); return $obj ; }
// Throw an exception if we get here throw new Exception ( "The class name $name could not be instantiated." ); } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Factory Method Pattern benefits:
Encapsulates object creation
Allows a range of functionality for error trapping, loading, etc
Does not need to know anything about what it is creating
Easy to read, easy to understand
Lightweight, fast and can be made into a static method
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Is there a way to tie all these patterns together into something usable?
I think we can, but first...
Object Oriented Design Patterns for PHP
The Strategy Pattern
The strategy pattern defines and encapsulates a set of algorithms and makes them interchangeable, allowing the algorithms to vary independent from the objects that use them.
Uh, what?
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern
Encapsulates what changes and leaves what doesn't change alone
Makes encapsulated algorithms interchangeable
Favors composition over inheritance
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
With some patterns, like the Strategy Pattern, the best way to ”get” it is to see it.
Let's have a look...
Object Oriented Design Patterns for PHP
The Strategy Pattern, part 1
<?php abstract class Computer { public $type ; public $platform ; abstract public function identify (); public function transport () { $this -> type -> transport (); } public function openTerminal () { $this -> platform -> terminal (); } public function closeTerminal () { echo "Close the terminal: type e-x-i-t, hit <enter>
" ; } public function setComputerType ( ComputerType $type ) { $this -> type = $type ; } public function setPlatform ( ComputerPlatform $platform ) { $this -> platform = $platform ; } public function gotoNext () { echo "Moving on...
" ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern, part 2
<?php interface ComputerType { public function transport (); } class ComputerType_Laptop implements ComputerType { public function transport () { echo "Transporting... Put the laptop in the bag and no one gets hurt.
" ; } } class ComputerType_Desktop implements ComputerType { public function transport () { echo "Transporting... Get the boxes, load it up, move it.
" ; } } class ComputerType_Server implements ComputerType { public function transport () { echo "Transporting... Seriously? Yeah, right. Transport this!
" ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern, part 3
<?php interface ComputerPlatform { public function terminal (); } class ComputerPlatform_Mac implements ComputerPlatform { public function terminal () { echo "Open the terminal: Go to applications -> terminal.
" ; } } class ComputerPlatform_Ubuntu implements ComputerPlatform { public function terminal () { echo "Open the terminal: Go to applications -> accessories -> terminal.
" ; } } class ComputerPlatform_Windows implements ComputerPlatform { public function terminal () { echo "Open the terminal: I am not smart enough to have a terminal but ...
" ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern, part 4
<?php class Computer_Mac extends Computer { public function __construct () { $this -> type = new ComputerType_Laptop ; $this -> platform = new ComputerPlatform_Mac ; } public function identify () { echo "I am a mac.
" ; } } class Computer_PC extends Computer { public function __construct () { $this -> type = new ComputerType_Desktop ; $this -> platform = new ComputerPlatform_Windows ; } public function identify () { echo "I'm a PC (or is that POS?).
" ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern, part 4 continued
<?php class Computer_Server extends Computer { public function __construct () { $this -> type = new ComputerType_Server ; $this -> platform = new ComputerPlatform_Ubuntu ; } public function identify () { echo "I am Ubuntu, one of a multitude of flavors of linux.
" ; } }
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern, part 5
<?php class Computer_Identifier { public function __construct () { $mac = new Computer_Mac ; $mac -> identify (); $mac -> openTerminal (); $mac -> closeTerminal (); $mac -> gotoNext ();
$linux = new Computer_Server ; $linux -> identify (); $linux -> transport (); } }
$comps = new Computer_Identifier ;
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
The Strategy Pattern, in action
I am a mac.
Open the terminal: Go to applications -> terminal.
Close the terminal: type e-x-i-t, hit <enter>
Moving on...
I'm a PC (or is that POS?).
Open the terminal: I am not smart enough to have a terminal but you can go to start -> all programs -> accessories -> command prompt.
Close the terminal: type e-x-i-t, hit <enter>
Moving on...
I am Ubuntu, one of a multitude of flavors of linux.
Transporting... Seriously? Yeah, right. Transport this!
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP
Notes about the Strategy Pattern
Probably one of the most common patterns in OOP
One of the most powerful patterns in development
Opens a wealth of possibility when understood
Very flexible when favoring composition over inheritance
Encapsulates what changes to allow for greater extendability
<?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?>
Object Oriented Design Patterns for PHP <?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?> Knowing what we know now, can you think of how these patterns can be applied to your applications to make for faster, more robust and cleaner application code? Maybe we can look at some code...
Object Oriented Design Patterns for PHP <?php if ( $this ->try && ! $this ->succeed()) $this ->try++; /* Robert Gonzalez, 2008-12-18 */ ?> Design patterns are a great way to modularize your code and create reusable structures. But they mean nothing if they go unused. Go code something. Much more information about design patterns, reusable code and object oriented programming can be found by simply typing those keywords into the Google search box :) http://www.robert-gonzalez.com [email_address]
1–3 of 3 previous next Post a comment