Showing posts with label php5. Show all posts
Showing posts with label php5. Show all posts

Saturday, May 23, 2009

The chain-of-command pattern using PHP

Building on the loose-coupling theme, the chain-of-command pattern routes a message, command, request, or whatever you like through a set of handlers. Each handler decides for itself whether it can handle the request. If it can, the request is handled, and the process stops. You can add or remove handlers from the system without influencing other handlers. Chain.php shows an example of this pattern.

Chain.php

<?php
interface ICommand {
function onCommand($name, $args);
}

class CommandChain {
private $_commands = array();

public function addCommand($cmd) {
$this->_commands []= $cmd;
}

public function runCommand($name, $args) {
foreach($this->_commands as $cmd) {
if ($cmd->onCommand($name, $args))
return;
}
}
}

class UserCommand implements ICommand {
public function onCommand($name, $args) {
if ($name != 'addUser') return false;
echo( "UserCommand handling 'addUser'\n" );
return true;
}
}

class MailCommand implements ICommand {
public function onCommand($name, $args) {
if ($name != 'mail') return false;
echo( "MailCommand handling 'mail'\n" );
return true;
}
}

$cc = new CommandChain();
$cc->addCommand( new UserCommand() );
$cc->addCommand( new MailCommand() );
$cc->runCommand( 'addUser', null );
$cc->runCommand( 'mail', null );
?>


This code defines a CommandChain class that maintains a list of ICommand objects. Two classes implement the ICommand interface -- one that responds to requests for mail and another that responds to adding users. The UML is shown in the figure.

The strategy pattern using PHP

In the strategy pattern, algorithms are extracted from complex classes so they can be replaced easily. For example, the strategy pattern is an option if you want to change the way pages are ranked in a search engine. Think about a search engine in several parts -- one that iterates through the pages, one that ranks each page, and another that orders the results based on the rank. In a complex example, all those parts would be in the same class. Using the strategy pattern, you take the ranking portion and put it into another class so you can change how pages are ranked without interfering with the rest of the search engine code.
As a simpler example, Strategy.php shows a user list class that provides a method for finding a set of users based on a plug-and-play set of strategies.

Strategy.php



<?php
interface IStrategy {
function filter($record);
}

class FindAfterStrategy implements IStrategy {
private $_name;

public function __construct($name) {
$this->_name = $name;
}

public function filter($record) {
return strcmp($this->_name, $record) <= 0;     } }  class RandomStrategy implements IStrategy {     public function filter($record) {         return rand(0, 1) >= 0.5;
}
}

class UserList {
private $_list = array();

public function __construct($names) {
if ($names != null) {
foreach($names as $name) {
$this->_list []= $name;
}
}
}

public function add($name) {
$this->_list []= $name;
}

public function find($filter) {
$recs = array();
foreach($this->_list as $user) {
if ($filter->filter($user))
$recs []= $user;
}
return $recs;
}
}

$ul = new UserList(array("Andy", "Jack", "Lori", "Megan"));
$f1 = $ul->find( new FindAfterStrategy("J") );
print_r($f1);

$f2 = $ul->find(new RandomStrategy());
print_r($f2);
?>

The observer pattern using PHP

The observer pattern gives you another way to avoid tight coupling between components. This pattern is simple: One object makes itself observable by adding a method that allows another object, the observer, to register itself. When the observable object changes, it sends a message to the registered observers. What those observers do with that information isn't relevant or important to the observable object. The result is a way for objects to talk with each other without necessarily understanding why.
A simple example is a list of users in a system. The code below shows a user list that sends out a message when users are added. This list is watched by a logging observer that puts out a message when a user is added.

Observer.php

<?php
interface IObserver {
function onChanged($sender, $args);
}

interface IObservable {
function addObserver($observer);
}

class UserList implements IObservable {
private $_observers = array();

public function addCustomer($name) {
foreach( $this->_observers as $obs )
$obs->onChanged( $this, $name );
}

public function addObserver( $observer ) {
$this->_observers []= $observer;
}
}

class UserListLogger implements IObserver {
public function onChanged( $sender, $args ) {
echo( "'$args' added to user list\n" );
}
}

$ul = new UserList();
$ul->addObserver( new UserListLogger() );
$ul->addCustomer( "Jack" );
?>


This code defines four elements: two interfaces and two classes. The IObservable interface defines an object that can be observed, and the UserList implements that interface to register itself as observable. The IObserver list defines what it takes to be an observer, and the UserListLogger implements that IObserver interface.

The singleton pattern using PHP

Some application resources are exclusive in that there is one and only one of this type of resource. For example, the connection to a database through the database handle is exclusive. You want to share the database handle in an application because it's an overhead to keep opening and closing connections, particularly during a single page fetch.
The singleton pattern covers this need. An object is a singleton if the application can include one and only one of that object at a time. The code below shows a database connection singleton in PHP5.

Singleton.php

<?php
require_once("DB.php");

class DatabaseConnection {
public static function get() {
static $db = null;
if ( $db == null )
$db = new DatabaseConnection();
return $db;
}

private $_handle = null;

private function __construct() {
$dsn = 'mysql://root:password@localhost/photos';
$this->_handle =& DB::Connect($dsn, array());
}

public function handle() {
return $this->_handle;
}
}

print("Handle = ".DatabaseConnection::get()->handle()."\n");
print("Handle = ".DatabaseConnection::get()->handle()."\n");
?>


This code shows a single class called DatabaseConnection. You can't create your own DatabaseConnection because the constructor is private. But you can get the one and only one DatabaseConnection object using the static get method.

The factory pattern using PHP

Many of the design patterns in the original Design Patterns book encourage loose coupling. To understand this concept, it's easiest to talk about a struggle that many developers go through in large systems. The problem occurs when you change one piece of code and watch as a cascade of breakage happens in other parts of the system -- parts you thought were completely unrelated.
The problem is tight coupling. Functions and classes in one part of the system rely too heavily on behaviors and structures in other functions and classes in other parts of the system. You need a set of patterns that lets these classes talk with each other, but you don't want to tie them together so heavily that they become interlocked.
In large systems, lots of code relies on a few key classes. Difficulties can arise when you need to change those classes. For example, suppose you have a User class that reads from a file. You want to change it to a different class that reads from the database, but all the code references the original class that reads from a file. This is where the factory pattern comes in handy.

The factory pattern is a class that has some methods that create objects for you. Instead of using new directly, you use the factory class to create objects. That way, if you want to change the types of objects created, you can change just the factory. All the code that uses the factory changes automatically.
Factory1.php shows an example of a factory class. The server side of the equation comes in two pieces: the database, and a set of PHP pages that let you add feeds, request the list of feeds, and get the article associated with a particular feed.

Factory1.php

<?php
interface IUser {
function getName();
}

class User implements IUser {
public function __construct( $id ) { }

public function getName() {
return "Jack";
}
}

class UserFactory {
public static function Create( $id ) {
return new User( $id );
}
}

$uo = UserFactory::Create( 1 );
echo( $uo->getName()."\n" );
?>






An interface called IUser defines what a user object should do. The implementation of IUser is called User, and a factory class called UserFactory creates IUser objects.