Everyday Design Patterns Andries Seutensx

35

description

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

Transcript of Everyday Design Patterns Andries Seutensx

Page 1: Everyday Design Patterns Andries Seutensx
Page 2: Everyday Design Patterns Andries Seutensx

Andries SeutensPHP Software Engineer,Sanmax Consultancy

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

http://twitter.com/[email protected]

[email protected]

Page 3: Everyday Design Patterns Andries Seutensx

Introduction to design patterns

What are they What are they not Where to use them

Common design patterns

Page 4: Everyday Design Patterns Andries Seutensx

Solutions to recurring design problems

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

this?!”

Help to understand frameworks

Page 5: Everyday Design Patterns Andries Seutensx

Pattern name

Problem description

Solution

Consequences

Page 6: Everyday Design Patterns Andries Seutensx

Silver bullet patternWill solve any programming problem

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

Page 7: Everyday Design Patterns Andries Seutensx
Page 8: Everyday Design Patterns Andries Seutensx

Library code

Full blown solutions

Page 9: Everyday Design Patterns Andries Seutensx
Page 10: Everyday Design Patterns Andries Seutensx

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

Page 11: Everyday Design Patterns Andries Seutensx

Problem Avoid tight coupling Concrete instantiation

Characteristics Common in toolkits and

frameworks Avoids dependency

Page 12: Everyday Design Patterns Andries Seutensx

Avoid copy / paste programming

Eases maintenance

Most common are database classes

Page 13: Everyday Design Patterns Andries Seutensx

$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'));

Page 14: Everyday Design Patterns Andries Seutensx

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

Page 15: Everyday Design Patterns Andries Seutensx

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();

Page 16: Everyday Design Patterns Andries Seutensx

Problem Global meltdown

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

Page 17: Everyday Design Patterns Andries Seutensx

$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;

Page 18: Everyday Design Patterns Andries Seutensx
Page 19: Everyday Design Patterns Andries Seutensx

Ease design by identifying simple ways to realize relationships between classes

We will look at 3 structural design patterns:

Data Mapper Decorator Adapter

Page 20: Everyday Design Patterns Andries Seutensx

Problem Object schema and the relational

schema don't match up

Characteristics Separates objects from the database

Page 21: Everyday Design Patterns Andries Seutensx

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() {}

}

Page 22: Everyday Design Patterns Andries Seutensx

Problem Overuse of inheritance Multiple inheritance

Characteristics Allows new/additional behavior An alternative to subclassing

Page 23: Everyday Design Patterns Andries Seutensx

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; }}

Page 24: Everyday Design Patterns Andries Seutensx

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

Page 25: Everyday Design Patterns Andries Seutensx
Page 26: Everyday Design Patterns Andries Seutensx

Increase flexibility and extensibility

We will look at these 2 behavioral patterns:

Strategy Observer

Page 27: Everyday Design Patterns Andries Seutensx

Problem Dynamically swap the algorithms used

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

backends

Page 28: Everyday Design Patterns Andries Seutensx

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); }}

Page 29: Everyday Design Patterns Andries Seutensx

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; }}

Page 30: Everyday Design Patterns Andries Seutensx

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

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

Page 31: Everyday Design Patterns Andries Seutensx

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

Page 32: Everyday Design Patterns Andries Seutensx

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();

Page 33: Everyday Design Patterns Andries Seutensx
Page 34: Everyday Design Patterns Andries Seutensx

Deal with multi-threaded programmingParadigm.

Simply put .... forget it

Page 35: Everyday Design Patterns Andries Seutensx