Everyday Design Patterns Andries Seutensx

Post on 01-Sep-2014

2.608 views 2 download

Tags:

description

A presentation about everyday design patterns, which I prepared for a local PHP UG meeting.

Transcript of Everyday Design Patterns Andries Seutensx

Andries SeutensPHP Software Engineer,Sanmax Consultancy

SME Zend Framework,Zend Technologies http://sanmax.be

http://twitter.com/andriesssandries@sanmax.be

a.seutens@telenet.be

Introduction to design patterns

What are they What are they not Where to use them

Common design patterns

Solutions to recurring design problems

Common language “Hey, let's use a factory pattern for

this?!”

Help to understand frameworks

Pattern name

Problem description

Solution

Consequences

Silver bullet patternWill solve any programming problem

Magic code factory patternCreates exactly the code you need for the problem by magic

Library code

Full blown solutions

Deal with object creational mechanisms

Create objects in a matter suitable to the situation

We will look at 3 creational design patterns Factory Singleton Registry

Problem Avoid tight coupling Concrete instantiation

Characteristics Common in toolkits and

frameworks Avoids dependency

Avoid copy / paste programming

Eases maintenance

Most common are database classes

$db = Zend_Db::factory('Pdo_Mysql', array( 'host' => '127.0.0.1', 'username' => 'webuser', 'password' => 'xxxxxxxx', 'dbname' => 'test'));

$db = Zend_Db::factory('Pdo_Oracle', array( 'host' => '127.0.0.1', 'username' => 'webuser', 'password' => 'xxxxxxxx', 'dbname' => 'test'));

Problem We need an application wide instance Require an exclusive resource

Characteristics Ensures a class only has one instance Provides a global point of access to it

class Singleton{

private static $_instance;

private function __construct() {}private function __clone() {}

public static function getInstance() {if (!self::$_instance instanceof self) {

self::$_instance = new self();}return self::$_instance;

}}

// Use case$foo = Singleton::getInstance();

Problem Global meltdown

Characteristics Can be used to find common objects Centers around PHP’s arrays

$config = new Zend_Config_Ini('my.ini', 'production');

// store config in registryZend_Registry::set('config', $config);

// somewhere else in your codebaseZend_Registry::get('config')->smtp->servername;

Ease design by identifying simple ways to realize relationships between classes

We will look at 3 structural design patterns:

Data Mapper Decorator Adapter

Problem Object schema and the relational

schema don't match up

Characteristics Separates objects from the database

class UserMapper{

public function save(User $user) {$data = array(

'username' => $user->getUsername(),'password' => sha1($user->getPassword()),

);$table = $this->getTable();$table->save($data);$user->setId($table->lastInsertId());

}public function getTable() {}

}

Problem Overuse of inheritance Multiple inheritance

Characteristics Allows new/additional behavior An alternative to subclassing

class CachingUserMapper{ $this->_mapper; public function __construct(UserMapper $mapper) { $this->_mapper = $mapper; } public function fetch($username) { $cache = $this->getCache(); if (($person = $cache->load($username)) === false) { $person = $this->_mapper->fetch($username); $cache->save($person, $username); } return $person; }}

Problem Convert an object of one type to an object of another typeHave multiple libraries use the same interface

CharacteristicsWraps to translate object into another interfaceAllows classes to work together

Increase flexibility and extensibility

We will look at these 2 behavioral patterns:

Strategy Observer

Problem Dynamically swap the algorithms used

Characteristics Defines a family of algorithms Unified API for use with various

backends

class UserList{ protected $_strategy; protected $_users; public function addUser($username) { $this->_users[] = $username; return $this; } public function sort(SortStrategy $strategy) { return $strategy->sort($this->_users); }}

abstract class SortStrategy{ abstract public function sort(Array $data);}

class AscendingSort extends SortStrategy{ public function sort(Array $data) { asort($data); return $data; }}

class DescendingSort extends SortStrategy{ public function sort(Array $data) { arsort($data); return $data; }}

$list = new UserList();$list->addUser('DragonBe');$list->addUser('Inventis');$list->addUser('Sanmax');

$ascending = $list->sort(new AscendingSort());$descending = $list->sort(new DescendingSort());

Problem Need to be able to notify and update dependents programatically when object's state changesEvent-driven programming at the scope of the application code

CharacteristicsNotifies observers on a state change

class ForumPost implements SplSubject{ protected $_observers = array(); protected $_content;

public function __construct($content) { $this->_content = $content; }

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

public function detach(SplObserver $observer) {}

public function notify() { foreach ($this->_observers as $obs) { $obs->update($this); } }

public function save() { $this->notify(); return $this; }}

class PostMailer implements SplObserver{ public function update(SplSubject $subject) { echo "emailing subscribed users\n"; }}

class PostFeedUpdater implements SplObserver{ public function update(SplSubject $subject) { echo "updating RSS feed\n"; }}

$post = new ForumPost('this is a new forum post');$post->attach(new PostMailer()) ->attach(new PostFeedUpdater()) ->save();

Deal with multi-threaded programmingParadigm.

Simply put .... forget it