Design Patterns 090322101222 Phpapp02

120
Simone Carletti, Altura Labs [email protected] Design Patterns in PHP

Transcript of Design Patterns 090322101222 Phpapp02

Page 1: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 1/120

Simone Carletti, Altura [email protected]

Design Patterns in PHP

Page 2: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 2/120

About me

  Technical Manager in Altura Labs  The first Zend Framework Italian contributor 

  Addicted to Agile Development and Development Best Practices

  Passionate about Object Oriented Programming

  I love pizza

Simone Carletti, Altura Labs

Page 3: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 3/120

.. and what about you?

Simone Carletti, Altura Labs

Page 4: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 4/120

Simone Carletti, Altura Labs

What’s wrong with this code?

Nothing…

…except all!

Hard Coded Actions

Presentation mixed

with business logic

Global Variables

Output mixed withelaboration

Context and responsibility conflicts

Page 5: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 5/120

Designing object oriented software is hard,and designing reusable object-orientedsoftware is even harder.

Design Patters (GoF)

Simone Carletti, Altura Labs

Page 6: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 6/120

Design Patterns

Simone Carletti, Altura Labs

Page 7: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 7/120

Design Patterns describe simple andelegant solutions to specific problems in

object oriented software design.

Simone Carletti, Altura Labs

Page 8: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 8/120

Christopher Alexander 

Simone Carletti, Altura Labs

Each pattern describes a problem which occursover and over again in our environment, and thendescribes the core of the solution to that problem,in such a way that you can use this solution a

million times over, without ever doing it the sameway twice.

Page 9: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 9/120

Christopher Alexander 

Simone Carletti, Altura Labs

Each pattern is a three-part rule, whichexpresses a relation between a certaincontext, a problem and a solution.

Page 10: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 10/120

The Gang of Four

Simone Carletti, Altura Labs

Page 11: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 11/120

Essential Elements

  Pattern name  A descriptive name for the pattern, in a word or two

  Problem

  Describes the problem the pattern applies to

  Solution  Describes the elements and the resources along with their relationship and

responsibilities for solving the problem.

  This is just an abstract description, the implementation varies according tothe programming language

  Consequences

  Results and trade-off 

Simone Carletti, Altura Labs

Page 12: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 12/120

What are Design Patterns

  Solution to common development problems  Reusable successful design and architectures

  Common language for developers

Simone Carletti, Altura Labs

Page 13: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 13/120

What Design Patterns are not

  The panacea for solving all development problems  Ready to use code scripts

  Cut & Paste solutions

Simone Carletti, Altura Labs

Page 14: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 14/120

Why Design Patterns?

 Help you to reuse successful design and architectures

  Help you to choose design alternatives

  Help you to solve problems you haven’t seen before

  Give a common vocabulary

  Let you communicate quickly and unambiguously

  Make a system more reusable

Simone Carletti, Altura Labs

Page 15: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 15/120

Design for Changes

The key to maximizing reuse lies in anticipating

new requirements and changes to existing

requirements, and in designing your systems so

that they can evolve accordingly.

Simone Carletti, Altura Labs

Design Patterns (GoF)

Page 16: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 16/120

Golden Rules

1. 

Program to an interface, not an implementation1.  Some languages takes this rule to the next level with Duck Typing

2.  Favor Object Composition over Inheritance

1.  Black Box approach

3.  Delegate

Simone Carletti, Altura Labs

Page 17: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 17/120

How to Select a Design Pattern

 Consider how to design patterns solve design problems

  Scan Intent section

  Study how patterns interrelate

  Study patterns of like purpose

  Examine a cause of redesign

  Consider what should be variable in your design

Simone Carletti, Altura Labs

Page 18: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 18/120

How to Use a Design Pattern

 Read the pattern once through for an overview

  Go back and study the Structure, Participants and Collaborationsections

  Look at the Sample Code section to see a concrete example of the

pattern in code  Choose names for pattern participants that are meaningful in the

application context

  Define the classes

  Define application-specific names for operations in the pattern  Implement the operations to carry out the responsibilities and

collaborations in the patterns

Simone Carletti, Altura Labs

Page 19: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 19/120

How to NOT Use a Design Pattern

 Don’t try to rewrite your application to fit a Design Pattern, selectthe best Pattern according to your needs

  Don’t use a Design Pattern because it’s cool… use a Patternbecause you need it

  Don’t copy/paste language-specific Pattern implementations,understand how the Pattern works and how you can implement it inyour application

Simone Carletti, Altura Labs

Page 20: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 20/120

A word of warning

Ideally, when the appropriate problem comes

along, you should trigger the design pattern and 

your problem is solved.

Simone Carletti, Altura Labs

Russ Olsen, Design Patterns in Ruby

Page 21: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 21/120

patterns : oop = notable products : algebra

The question isn't whether you'll encounter most patternsbut whether you'll recognize them when they cross your 

 path. Will you know how to cleanly solve the problem

represented by the pattern, or will you stumble thought

several code iterations before you find an acceptable

solutions? 

Simone Carletti, Altura Labs

Ship it!

Page 22: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 22/120

Design for Changes

Do you remember? But we careful…

Simone Carletti, Altura Labs

Page 23: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 23/120

Avoid Over-Engineering

Simone Carletti, Altura Labs

Page 24: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 24/120

Avoid Under-Engineering

Simone Carletti, Altura Labs

Page 25: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 25/120

Don’t fall into the

“everything is a pattern” trap

Simone Carletti, Altura Labs

Page 26: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 26/120

Frameworks vs Design Patterns

 Design patterns are more abstract than frameworks

  Design patterns are smaller architectural elements thanframeworks

  Design patterns are less specialized than frameworks

  A typical framework contains several design patterns, but thereverse is never true

Simone Carletti, Altura Labs

Page 27: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 27/120

Helpful Agile methodologies

 Refactoring  Do you really need this Pattern now?

  You Ain't Gonna Need It

  Refactoring to Pattern

  Unit Test

  Always have a consistent test suite before refactoring your code

  Test-Driven Development

Simone Carletti, Altura Labs

Page 28: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 28/120

Design Pattern Classification

Simone Carletti, Altura Labs

Page 29: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 29/120

Design Patterns by Purpose

 Creational Patterns  Concern the process of object creation

  Structural Patterns

  Deal with the composition of object and classes

  Behavioral Patterns  Characterize the way in which classes or objects interact

  Concurrency Patterns

  Architectural Patterns

  …

Simone Carletti, Altura Labs

Page 30: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 30/120

Design Patterns by Scope

 Class PatternsDeal with relationships between classes and their subclasses.

Ex. Factory Method, Adapter, Template method…

  Object PatternsDeal with object relationships.

The most part of patterns are in the object scope.

Ex. Singleton, Adapter, Decorator, Proxy, Iterator, Observer…

Simone Carletti, Altura Labs

Page 31: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 31/120

Design Patterns

 Architectural  MVC

  Creational

  Singleton

  Factory Method  Lazy initialization

  Structural

  Adapter 

  Proxy

 Behavioral   Iterator 

  Observer 

  Strategy

  Template Method

  More

  Registry

  Mock Object

Simone Carletti, Altura Labs

Page 32: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 32/120

Q & A(part 1/2)

Simone Carletti, Altura Labs

Page 33: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 33/120

Design Patterns in Action

Simone Carletti, Altura Labs

Page 34: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 34/120

Pattern Template

 Problem & Solution

  Considerations

  In pictures

  Implementation & Examples

  In the Wild

  Using and Abusing

Simone Carletti, Altura Labs

Page 35: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 35/120

MVC

Simone Carletti, Altura Labs

Page 36: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 36/120

MVC: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You want an efficient designsolution to split the view fromthe business logic of your application

  You want to keep your application reusable bysplitting the design in multiple

layers

  The MVC pattern decouplesviews and models byestablishing a subscribe/notifyprotocol between them

  A view reflects the state of themodel

  This approach enables you to

attach multiple view to amodel an provide differentrepresentations

Page 37: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 37/120

MVC: in pictures

Simone Carletti, Altura Labs

http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/ 

Page 38: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 38/120

MVC: Model, View and Controller

Simone Carletti, Altura Labs

 The model is the domain-specific representation of data. It usuallyconsists in a database or some other storage system.

  The view renders the model in a form suitable according to therequest. This layer is commonly known with the word template.

  The controller processes the requests and it’s in charge of queryingthe model and returning the right template according to the request.

Page 39: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 39/120

MVC: decoupling View and Model

Simone Carletti, Altura Labs

Articles

Article::find()

XML Feed iPhone(X)HTML

$articles

$articles$articles

Page 40: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 40/120

MVC: in the wild

Simone Carletti, Altura Labs

 The most part of PHP web frameworks implement the MVC pattern, including Symfony, Zend Framework, CakePHP…

  The most part of modern PHP applications inherit some principlesfrom MVC pattern.

  Many applications use a template engine

  Many applications separate the model from the view and interact with thedatabase via ORM frameworks

Page 41: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 41/120

MVC: Single Responsibility Principle

Simone Carletti, Altura Labs

 Every object should have a single responsibility, and that all itsservices should be narrowly aligned with that responsibility.

  The most frequent error using MVC is to execute operations in thewrong context

Page 42: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 42/120

MVC: find the error (1)

Simone Carletti, Altura Labs

class BookController{   public function SuggestionsAction()

{  $firstChoice = Book::findAll(  array(  'conditions' => array('name LIKE ?', '%'.$params['query']),   'order' => 'weight DESC'

));

  $secondChoice = Book::findAll(  array(  'conditions' => array('name LIKE ?', '%'.$params['query'].'%'),

'order' => 'weight DESC')

);  $this->choices = array_merge($firstChoice, $secondChoice);  $this->render('suggestions');

}} 

Page 43: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 43/120

MVC: find the error (1/solution)

Simone Carletti, Altura Labs

// BookController represents the Book controllerclass BookController{   public function SuggestionsAction()

{  $this->choices = Book::findSuggestionsForKeyword($params['query']);  $this->render('suggestions');

}}// Book class represent the Book modelclass Book {  public static function findSuggestionsForKeyword($query) {  $firstChoice = self::findAll(  array(  'conditions' => array('name LIKE ?', '%'.$params['query']),   'order' => 'weight DESC'

));

  $secondChoice = self::findAll(  array(  'conditions' => array('name LIKE ?', '%'.

$params['query'].'%'),   'order' => 'weight DESC'

));

  return array_merge($firstChoice, $secondChoice);}

}

Page 44: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 44/120

MVC: find the error (2)

Simone Carletti, Altura Labs

<h2>Available Tickets</h2><?php$tickets = Ticket::findAll(array('conditions' => array('published' => true)));

$available = array();foreach($tickets as $ticket) {  if ($currentUser->isAdmin() == true || $ticket->isPublic()) {  $available[] = $ticket;

}}?><ul><?php foreach($available as $ticket) { ?>

<li><?php echo $ticket->title == '' ?   'This ticket has no title' :   $ticket->title . ' ' . $ticket->price; ?></li><?php } ?></ul> 

Page 45: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 45/120

MVC: find the error (2/solution)

Simone Carletti, Altura Labs

// define formatters in your model// only when formatters are not tied to// one or more specific viewsclass Ticket {  // ...  public function getFormattedTitle()

{  return $ticket->title == '' ?   'This ticket has no title' :   $ticket->title .   ' ' . 

  $ticket->price;

}}// or delegate the responsibility to the view usinghelpersclass TicketsHelper{  public static function formatTitle($ticket)

{  return  $ticket->title == '' ?   'This ticket has no title' :   $ticket->title .   ' ' .   $ticket->price;

}}

<h2>Available Tickets</h2><ul><?php foreach($tickets as $ticket) { ?><li><?php $ticket->getFormattedTitle(); ?>

</li><?php } ?></ul><!-- or using helpers --><h2>Available Tickets</h2><ul><?php foreach($tickets as $ticket) { ?><li><?php TicketsHelper::formatTitle($ticket) ?>

</li><?php } ?>

</ul>

// the controller knows about User's ACL// and runs the appropriate query through the modelclass TicketsController{  public function AvailableAction(){  if ($currentUser->isAdmin()) {  $tickets = Ticket::findAll();

} else {  $tickets = Ticket::findAllPublic();

}$this->ticket = $tickets;

}}

Controller 

View

Model

Helper 

Page 46: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 46/120

Singleton

The Highlander 

Simone Carletti, Altura Labs

Page 47: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 47/120

Singleton: problem & solution

Problem

  You want a class to haveexactly one instance

  You want the instance to beeasily accessible

  You don’t want to use globalvariables

Solution

  The Singleton pattern ensuresa class has only one instance,and provide a global point toaccess it

Simone Carletti, Altura Labs

Page 48: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 48/120

Singleton: considerations

Simone Carletti, Altura Labs

  Often used for shared objects such as configurations, queues,database connections…

  You don’t want the environment to be responsible of classinstantiation

  You don’t want the environment to be responsible of avoid multipleclass instances

  The Singleton is often a mixed behavior 

Page 49: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 49/120

Singleton: implementation

Simone Carletti, Altura Labs

class Singleton{  // holds the singleton instance  private static $_instance = null;

  // redefined as private to be called only// from within the class scope

  private function __construct(){}

  // redefined to deny object clones  public function __clone()

{  throw new Exception('You cannot clone Singleton object');

}

  public function getInstance(){

  if (null === self::$_instance) {

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

}} 

Page 50: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 50/120

Singleton: example

Simone Carletti, Altura Labs

class Singleton{

  // holds the singleton instance  private static $_instance = null;

  // redefined as private to be called only// from within the class scope

  private function __construct(){}

  // redefined to deny object clones

  public function __clone(){  throw new Exception('You cannot clone Singleton object');

}

  public function getInstance(){

  if (null === self::$_instance) {  self::$_instance = new Singleton();

}  return self::$_instance;

}}

$instance = Singleton::getInstance();$instance->doSomething();

Singleton::getInstance()->doSomething();Singleton::getInstance()->doSomething()->thenSomethingElse();

Page 51: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 51/120

Singleton: Class as Singleton

Simone Carletti, Altura Labs

  You can declare methods as static and use the class as thecontainer for the Singleton functionality

  You are sure no one will create additional instances

  You can’t take advantage of other patterns, such as LazyInitialization

  You don’t have control over initialization

  You don’t have access to the instance context

  It’s not thread safe

Page 52: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 52/120

Singleton: Why not using Global Variables?

Simone Carletti, Altura Labs

  There’s no way to control the value of a global variable

  Doesn’t prevent someone from creating multiple instances

  Global variables are unpredictable

  Global variables are difficult to debug and test

  Global variables are unsecure

  Global variable makes the code difficult to read

Page 53: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 53/120

Singleton: in the wild

Simone Carletti, Altura Labs

  Pake, the Symfony PHP-make library

  Doctrine_Manager, the base component of all Doctrine basedprojects. It opens and keeps track of all database connections

  Many components of the Symfony framework, including

 sfContext

  sfAutoload

  sfCultureInfo

  The configuration class ConfigFile in phpMyAdmin

Page 54: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 54/120

Singleton: using & abusing

Simone Carletti, Altura Labs

  Before applying a Singleton ask yourself: do I really need aSingleton?

  Look at your code, check the number of a class instances

  Beware to not spread the Singleton knowledge in classes whereyou don’t really need to

  To all intents and purposes, a Singleton instance is a normal classinstance, you can pass it as a parameter 

Page 55: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 55/120

Factory Method

Simone Carletti, Altura Labs

Page 56: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 56/120

Factory Method: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You want to create aninstance of a class but youdon’t know in advance the

object class you need to use

  You want to localize theknowledge of which classmust be instantiated

  The Factory Method patterndefines an interface for creating an object, but lets

subclasses decide whichclass to instantiate.

  The Factory Method defersinstantiation

Page 57: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 57/120

Factory Method: considerations

Simone Carletti, Altura Labs

  It’s difficult to find in PHP an original implementation of the FactoryMethod as defined by the GoF

  There are different variation to the original Factory Method

  The GoF discussed both Factory Method and Abstract Factory

Page 58: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 58/120

Factory Method: example

Simone Carletti, Altura Labs

public static function factory($uri = 'http'){  // Separate the scheme from the scheme-specific parts  $uri  = explode(':', $uri, 2);  $scheme  = strtolower($uri[0]);  $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';  if (strlen($scheme) === 0) {  require_once 'Zend/Uri/Exception.php';  throw new Zend_Uri_Exception('An empty string was supplied for the scheme');

}  // Security check: $scheme is used to load a class file, so only alphanumerics are allowed.  if (ctype_alnum($scheme) === false) {  require_once 'Zend/Uri/Exception.php';  throw new Zend_Uri_Exception('Illegal scheme supplied, only alphanumeric characters arepermitted');

}  /**

* Create a new Zend_Uri object for the $uri. If a subclass of Zend_Uri exists for the* scheme, return an instance of that class. Otherwise, a Zend_Uri_Exception is thrown.*/

  switch ($scheme) { /* factory pattern implementation */ }  Zend_Loader::loadClass($className);  $schemeHandler = new $className($scheme, $schemeSpecific);  return $schemeHandler;}

Page 59: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 59/120

Factory Method: example

Simone Carletti, Altura Labs

public static function factory($uri = 'http'){  // ...  switch ($scheme) {  case 'http':  // Break intentionally omitted  case 'https':  $className = 'Zend_Uri_Http';  break;  case 'mailto':

  // TODO  default:  require_once 'Zend/Uri/Exception.php';  throw new Zend_Uri_Exception("Scheme \"$scheme\" is not supported");  break;

}  Zend_Loader::loadClass($className);  $schemeHandler = new $className($scheme, $schemeSpecific);  return $schemeHandler;}

Page 60: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 60/120

Factory Method: in the wild

Simone Carletti, Altura Labs

  Zend_Uri::factory() returns the right Zend_Uri subclass accordingto the type of URI passed as parameter 

  Zend_Cache::factory() returns the best Zend_Cache enginesaccording to given options and configurations

  Doctrine contains several implementation of the Factory pattern.

For example Doctrine_Node::factory() return node instance basedupon chosen implementation

Page 61: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 61/120

Factory Method: using & abusing

Simone Carletti, Altura Labs

  Use the Factory Method only if you really need it

  Don’t anticipate future needs, refactoring is usually the right choice

  Plans might change and you just spent time building useless, heavyinfrastructures

  Be Smart! Be Agile! Be Lazy!

Page 62: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 62/120

Lazy Initialization

Lazy evaluation

Simone Carletti, Altura Labs

Page 63: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 63/120

Lazy Initialization: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You want to delay the creationof an instance or anexpensive operation until the

first time it is needed

  You want the operation to beexecuted only when and if necessary

  The Lazy Initialization patterndelays the creation of anobject or the execution of an

expensive process until thefirst time it is needed

Page 64: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 64/120

Lazy Initialization: example

Simone Carletti, Altura Labs

class PluginManager {protected $_plugins;

  public function getPlugins() {  // parse list once only when needed and store it in memory  if (null === $this->_plugins) {

$this->_plugins = $this->parsePluginList();}return $this->parsePluginList();

}

public function activate($class) {  require_once $class; // require the class once

$plugin = new $class; // only if and when needed$plugin->activate();

}

public function deactivate($class) {  if (!isActive($class)) {  require_once 'Plugin_Not_Active_Exception.php';  throw new PluginNotActiveException("Plugin $class not active");

}  $plugin = new $class;

$plugin->deactivate();}

  // check whether $class is in getPlugins()  protected function isActive($class) { /* */ }

// scans a folder tree looking for plugin files// this is a really expensive operation

  protected function parsePluginList() { /* */ }}

Page 65: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 65/120

Lazy Initialization: in the wild

Simone Carletti, Altura Labs

  The most part of Zend_Exception classes in Zend Framework arelazy-loaded

  Controller classes in Symfony, Zend Framework and (almost) everyPHP Framework are lazy-loaded

  Many resources in Xoops, such as the ReplacementArray, are

lazy-instantiated

  Drupal maintains an internal registry of functions or classes in thesystem, allowing it to lazy-load code files as needed

Page 66: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 66/120

Adapter

Simone Carletti, Altura Labs

Page 67: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 67/120

Adapter: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You want to reuse a library inyour application but it doesn’tmatch your interface

  You want to normalizemultiple libraries to use thesame interface

  The Adapter pattern convertsthe interface of a class intoanother interface clients

expect

  Adapter lets classes worktogether that couldn’totherwise because of incompatible interfaces

Page 68: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 68/120

Adapter: considerations

Simone Carletti, Altura Labs

  Adapter is a common pattern when using third party libraries

  If you are developing your own libraries, you might want to avoidadapters and use common habits and guidelines

  Often using in cooperation with other patterns, such as the Strategypattern

  Adapt or Modify?

  Adapter pattern and Proxy pattern are similar, but they havedifferent intents. Adapter is meant to change the interface of anexisting object

Page 69: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 69/120

Adapter: example

Simone Carletti, Altura Labs

class MySQL_Connection {  public static function connect($host, $user, $pass)

{  // main connection logic

}}class PostgreSQL {  public static function do_connect($args = array())

{  // main connection logic}}class OracleCoolLibrary {  public function __construct($args = array())

{  // main connection logic

}  public function connect()

{  // main connection logic

}}

Page 70: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 70/120

Adapter: example

Simone Carletti, Altura Labs

class MySQL_Adapter extends MySQL_Connection{  public static function connect($params)

{

  $host, $user, $pass = list($params);  parent::connect(array($host, $user, $pass))

}}class PostgreSQL_Adapter extends PostgreSQL{  public static function connect($params)

{  self::do_connect($params);

}}class Oracle_Adapter extends OracleCoolLibrary {  public static function connect($params)

{  $instance = new OracleCoolLibrary($params);  $instance->connect();

}}

class MySQL_Connection {  public static function connect($host, $user, $pass)

{

  // main connection logic}

}

class PostgreSQL {  public static function do_connect($args = array())

{  // main connection logic

}}class OracleCoolLibrary {  public function __construct($args = array())

{  // main connection logic}  public function connect()

{  // main connection logic

}}

Page 71: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 71/120

Adapter: in the wild

Simone Carletti, Altura Labs

  Zend_Db and all the database-specific subclasses

  Zend_Http_Client provides different adapters for different purposes(including a test adapter)

  Doctrine DBAdapter and database-specific subclasses

Page 72: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 72/120

Adapter: using & abusing

Simone Carletti, Altura Labs

  Avoid creating adapter of adapters

  Go to the main library and build the Adapter at the lowest possiblelevel

Page 73: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 73/120

Proxy

Simone Carletti, Altura Labs

Page 74: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 74/120

Proxy: problem & solution

Problem

  You need to provide access toan object without exposing theobject directly

  You want to control access tothat object

  You want to filter access tothat object

Solution

  The Proxy pattern provides asurrogate or placeholder for an other object to control

access to it

Simone Carletti, Altura Labs

P

Page 75: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 75/120

Proxy: considerations

  The Proxy is build around a lie

  You might want to expose a similar public API

  Remember: composition over inheritance

  Duck Typing or Interface

 You might want to improve performance for expensive operations

Simone Carletti, Altura Labs

P

Page 76: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 76/120

Proxy: example

Simone Carletti, Altura Labs

// This class represents a simple bank accountclass Account {  protected $balance;  public function __construct()

{}

  public function deposit($amount){

  $this->balance += (int) $amount;  return $this;}

  public function withdraw($amount){

  $this->balance -= (int) $amount;  return $this;

}  public function getBalance()

{

  return $this->balance;}

P

Page 77: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 77/120

Proxy: example

Simone Carletti, Altura Labs

class AccountProxy{  protected $account;  public function __construct($account)

{  $this->account = $account;  return $this;

}  public function deposit($amount)

{  $this->account->deposit($amount);  return $this;

}  public function withdraw($amount)

{  $this->account->withdraw($amount);  return $this;

}  public function getBalance()

{  return $this->account->getBalance();

}}

$proxy = new AccountProxy(new Account());$proxy->deposit(20)->withdraw(5);print $proxy->getBalance(); 

P

Page 78: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 78/120

class AccountProxy{  protected $account;  public function __construct($account)

{  $this->account = $account;  return $this;

}  public function deposit($amount)

{  $this->account->deposit($amount);  return $this;

}  public function withdraw($amount)

{  $this->account->withdraw($amount);  return $this;

}  public function getBalance()

{

  return $this->account->getBalance();}

}

Proxy: example with Lazy Instantiation pattern

Simone Carletti, Altura Labs

class AccountProxy{  protected $account;  public function deposit($amount)

{  $this->getAccount()->deposit($amount);  return $this;

}  public function withdraw($amount)

{  $this->getAccount()->withdraw($amount);  return $this;

}  public function getBalance()

{  return $this->getAccount()->getBalance();

}  protected function getAccount()

{  if (null === $this->account) {  $this->account = new Account();

}  return $this->account;

}} 

P

Page 79: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 79/120

Proxy: Virtual Proxy

Simone Carletti, Altura Labs

class AccountProxy{  protected $account;  public function deposit($amount)

{  $this->getAccount()->deposit($amount);  return $this;

}  public function withdraw($amount)

{  $this->getAccount()->withdraw($amount);  return $this;

}  public function getBalance()

{  return $this->getAccount()->getBalance();

}  protected function getAccount()

{

  if (null === $this->account) {  $this->account = new Account();

}  return $this->account;

}} 

account

 __call

$args

$this or $value

class AccountProxy{  protected $account;  public function __call($name, $args)

{  $account = $this->getAccount();  if (!is_callable(array(&$account, $name))) {  throw new Exception("No method $name");

}  $params = array(&$account, $name) ;   $return = call_user_func_array($params, $args);  return $return === $account ? $this : $return;

}  protected function getAccount()

{  if (null === $this->account) {  $this->account = new Account();

}  return $this->account;

}}

P

Page 80: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 80/120

Proxy: in the wild

Simone Carletti, Altura Labs

  PHP 5 SOAP Library has examples of Remote Proxy in the WSDL

mechanism

  Many classes in Symfony provide proxy methods to shorten thecode needed for get/set operations

  $request->getParameterHolder()->set('foo', 'bar');

  $request->setParameter('foo', 'bar');

P

Page 81: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 81/120

Proxy: using & abusing

Simone Carletti, Altura Labs

  Don’t forget to redefine special class methods accordingly

   __clone

   __get

   __set

   __toString

  …

  Avoid responsibility-mistakes

  Be sure all classes are well documented, especially when usingvirtual proxies and difficult-to-auto-document features

Page 82: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 82/120

Iterator

Simone Carletti, Altura Labs

Page 83: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 83/120

Iterator: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You have a complexaggregate object and youwant to access its elements

without working onimplementation

  You want to traverse andmanipulate a collection object

  The Iterator pattern provides away to access the elements of an aggregate object

sequentially without exposingthe underlying representation

Iterator

Page 84: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 84/120

Iterator: considerations

Simone Carletti, Altura Labs

  You might not realize it, but you use the Iterator pattern every day

working with Arrays

Iterator l

Page 85: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 85/120

Iterator: example

Simone Carletti, Altura Labs

$colors = array('yellow', 'orange', 'green');foreach($colors as $color) {  print "Current color: $color\n";}

$items = array(  'first'  => 1,  'second'  => 2,  'third'  => 3,

);foreach($items as $key => $value) {  print "Value $value for key $key\n";} 

Iterator SPL l

Page 86: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 86/120

Iterator: SPL example

Simone Carletti, Altura Labs

class Zend_Service_Amazon_ResultSet implements SeekableIterator{  /**

* A DOMNodeList of <Item> elements*/

  protected $_results = null;  /**

* Current index for SeekableIterator*/

  protected $_currentIndex = 0;/*** Implement SeekableIterator::current()** @return Zend_Service_Amazon_Item*/

  public function current(){

  return new Zend_Service_Amazon_Item($this->_results->item($this->_currentIndex));}

  /*** Implement SeekableIterator::key()** @return int*/

  public function key(){

  return $this->_currentIndex;}

Iterator SPL l

Page 87: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 87/120

Iterator: SPL example

Simone Carletti, Altura Labs

/*** Implement SeekableIterator::next()*/

  public function next() {  $this->_currentIndex += 1;

}  /**

* Implement SeekableIterator::rewind()*/

  public function rewind() {  $this->_currentIndex = 0;

}  /*** Implement SeekableIterator::seek()

*/  public function seek($index) {  $indexInt = (int) $index;  if ($indexInt >= 0 && (null === $this->_results || $indexInt < $this->_results->length)) {  $this->_currentIndex = $indexInt;

} else {  throw new OutOfBoundsException("Illegal index '$index'");

}}

  /*** Implement SeekableIterator::valid()*/

  public function valid() {  return null !== $this->_results && $this->_currentIndex < $this->_results->length;

}}

Iterator PHP 5 SPL

Page 88: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 88/120

Iterator: PHP 5 SPL

Simone Carletti, Altura Labs

  SPL offers some advanced Iterator algorithms

  Iterator 

  RecursiveIterator 

  SeekableIterator 

  ArrayIterato

  Don’t forget to have a look at the Countable interface

Iterator i th ild

Page 89: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 89/120

Iterator: in the wild

Simone Carletti, Altura Labs

  PHP 5 DirectoryIterator library

  Zend_Feed, Zend_Service_Amazon, Zend_Service_Technorati inthe Zend Framework

Iterator i g & b i g

Page 90: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 90/120

Iterator: using & abusing

Simone Carletti, Altura Labs

  Limit (or avoid) using iterators for changing internal object status

  Don’t fall into the concurrent modification trap!

  Be sure you are not altering iterator internal index

Page 91: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 91/120

Observer

Simone Carletti, Altura Labs

Observer: OMG!

Page 92: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 92/120

Observer: OMG!

Simone Carletti, Altura Labs

class User {  protected $_logger;  protected $_username;  public function __construct($username, $notifier)

{  $this->_username = $username;  $this->_logger = new Logger();  $this->_notifier = $notifier;

}  public function setUsername($username)

{  $this->_username = $username;  $this->_logger->debug("$username changed username");  $this->_notifier->userChangedLogin($this);

}  public function login($password)

{  // login login  $this->_logger->debug("$username logged in");

}} 

Ob

Page 93: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 93/120

Observer: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You want objects to interacteach other without making theclasses tightly coupled

  You need to maintainconsistency between relatedobjects with data integrity inmind

  The Observer pattern definesdependency between objectsso that when one object

change state, all itsdependents are notified andupdated automatically

Observer: implementation

Page 94: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 94/120

Observer: implementation

Simone Carletti, Altura Labs

class Subject{

protected $_observers = array();

  public function attach($observer){

$this->_objservers[] = $observer;}

  public function detach($observer){

$observers = array();

  foreach($this->_observers as $object) {  if ($object !== $observer) {$observers[] = $object;

}}$this->_observers = $observers;

}

  public function notify(){

  foreach($this->_observers as $observer) {

$observer->update($this);}

}} 

Observer: example

Page 95: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 95/120

Observer: example

Simone Carletti, Altura Labs

class User {  protected $_username;  protected $_observers = array();  public function attach($observer)

{  // ... see implementation

}  public function detach($observer)

{

  // ... see implementation}

  public function notify(){

  // ... see implementation}

  public function setUsername($username){

  $this->_username = $username;  $this->notify();

}}

$user = new User();$user->attach(new Logger());$user->attach(Notifier::getInstance());$user->setUsername('foobar');

Observer: PHP 5 SPL

Page 96: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 96/120

Observer: PHP 5 SPL

Simone Carletti, Altura Labs

  SPL suggests a standard way of implementing the Observer  

pattern.

  interface SplObserver 

  interface SplSubject

  class SplObjectStorage

Observer: in the wild

Page 97: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 97/120

Observer: in the wild

Simone Carletti, Altura Labs

  Zend_XmlRpc_Server_Fault in Zend Framework accepts a list of 

observers and notifies them in case of unexpected behaviors

Observer: using & abusing

Page 98: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 98/120

Observer: using & abusing

Simone Carletti, Altura Labs

  Don’t notify observers if you don’t need

  Consider to add specific notifications if you find yourself callingupdate() too many times for different kind of notifications

  ->update()

  ->save()

  ->delete()

  Be careful to notify observers only when a consistent change iscomplete.

  Remember, your object should provide a way to let observers know

what changed

Page 99: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 99/120

Template Method

Simone Carletti, Altura Labs

T l t M th d

Page 100: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 100/120

Template Method: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  The Template Method patterndescribes the skeleton of analgorithm in an operation,

deferring some steps tosubclasses

  Template Method letssubclasses redefine certainsteps of an algorithm without

changing the algorithm’sstructure

  You have a complex comethat might vary somewhere inthe middle

  You want to let subclasseschange part of the abstractclass algorithms

  You want to defer to

implementations some partsof an algorithms

Template Method: considerations

Page 101: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 101/120

Template Method: considerations

Simone Carletti, Altura Labs

  Template Method is based on inheritance

  Strategy pattern can be considered the composition variant

Template Method: implementation

Page 102: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 102/120

Template Method: implementation 

Simone Carletti, Altura Labs

abstract class AbstractClass {  public final function templateMethod()

{  print "AbstractClass::templateMethod()\n";  $this->mandatoryMethod();  $this->optionalMethod();

}  protected abstract function mandatoryMethod();  protected function optionalMethod()

{  print "AbstractClass::optionalMethod()\n";

}}class FirstConcreteClass extends AbstractClass {  protected function mandatoryMethod() {  print "FirstConcreteClass::mandatoryMethod()\n";

}}class SecondConcreteClass extends AbstractClass

{  protected function mandatoryMethod() {  print "SecondConcreteClass::mandatoryMethod()\n";

}  protected function optionalMethod() {  print "SecondConcreteClass::optionalMethod()\n";

}}

$o = new FirstConcreteClass;$o->templateMethod();# AbstractClass::templateMethod()# FirstConcreteClass::mandatoryMethod()# AbstractClass::optionalMethod()$o = new SecondConcreteClass;$o->templateMethod();# AbstractClass::templateMethod()# SecondConcreteClass::mandatoryMethod()# SecondConcreteClass::optionalMethod() 

Template Method: example

Page 103: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 103/120

Template Method: example

Simone Carletti, Altura Labs

abstract class Page{  protected $_title;  protected $_content;  public function __construct($title, $content) {  $this->_title = $title;  $this->_content = (array) $content;

}  public final function generate() {  $this->generateHeader();  $this->generateTitle();  $this->generateBodyHeader();  $this->generateBody();  $this->generateBodyFooter();  $this->generateFooter();

}  protected abstract function generateHeader();  protected abstract function generateBodyHeader();  protected abstract function generateBodyFooter();  protected abstract function generateFooter();  protected abstract function generateLine($line);  protected function generateTitle() {  printf("Title: %s\n", $this->_title);

}  protected final function generateBody() {  foreach($this->_content as $line) {  $this->generateLine($line);

}}

}

Template Method: example

Page 104: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 104/120

Template Method: example

Simone Carletti, Altura Labs

class HtmlPage extends Page {  protected function generateHeader() {  printf("<html>\n");

}  protected function generateTitle() {  printf("<head><title>%s</title></head>\n",  $this->_title);

}  protected function generateBodyHeader() {  printf("<body>\n");

}  protected function generateBodyFooter() {  printf("</body>\n");

}  protected function generateFooter() {  printf("</html>\n\n");

}  protected function generateLine($line) {  printf($line);

}}

class FeedPage extends Page {  protected function generateHeader() {  printf("<?xml version=\"1.0\"?>\n");  printf("<rss version=\"2.0\">\n");  printf(" <channel>\n");

}  protected function generateTitle() {  $title = $this->_title;  printf(" <title>%s</title>\n", $title);

}  protected function generateBodyHeader() {}  protected function generateBodyFooter() {

}  protected function generateFooter() {  printf(" </rss>\n");  printf("</channel>\n\n");

}  protected function generateLine($line) {  printf(" <item><title>%s</title></item>\n",  $line);

}

}

Template Method: example

Page 105: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 105/120

Template Method: example

Simone Carletti, Altura Labs

$t = 'This is the title';$c = array('First entry', 'Second entry');$o = new FeedPage($t, $c);$o->generate();$o = new HtmlPage($t, $c);$o->generate(); 

<?xml version="1.0"?><rss version="2.0"><channel><title>This is the title</title><item><title>First entry</title></item><item><title>Second entry</title></item></rss>

</channel><html><head><title>This is the title</title></head><body>First entrySecond entry</body></html> 

Template Method: in the wild

Page 106: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 106/120

Template Method: in the wild

Simone Carletti, Altura Labs

  Propel bases the full public API on a custom implementation of the

Template Method pattern.  BaseClass is the “abstract” class

  Class extends BaseClass and overwrites only those methods you want tocustomize

Template Method: using & abusing

Page 107: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 107/120

e plate Met od: using & abusing

Simone Carletti, Altura Labs

  Avoid creating abstract classes that forces concrete classes to

implement tons of methods

Page 108: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 108/120

Strategy

Simone Carletti, Altura Labs

Strategy bl & l ti

Page 109: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 109/120

Strategy: problem & solution

Problem Solution

Simone Carletti, Altura Labs

  You have a complex operationthat might vary algorithms atruntime and you want to

encapsulate algorithms  You want to be able to easily

test the algorithms

  You want to be able to add,

remove or change analgorithm without changingthe global operation logic

  The Strategy pattern defines afamily of algorithms,encapsulate each one, and

make them interchangeable  Strategy lets the algorithm

vary independently fromclients that use it, often atruntime level

Strategy: considerations

Page 110: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 110/120

gy

Simone Carletti, Altura Labs

  Strategy is an excellent example of composition and delegation

  Strategy is an alternative to subclassing

  Strategy and Template Method patterns expose different approachto a similar problem

  Duck Typing is a common practice in Strategy pattern

Strategy: example

Page 111: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 111/120

gy p

Simone Carletti, Altura Labs

interface Sorter {  public function sort();}class SelectionSort implements Sorter{  public function sort($array)

{  // selection sort algorithm

}}class InsertionSort implements Sorter{  public function sort($array)

{  // insertion sort algorithm

}}class SuperSecretSort implements Sorter{  public function sort($array){  // insertion sort algorithm

}}

class ArraySorter {  protected $_a;  public function __construct($a)

{  $this->_a;  return self;

}  public function sortWithAlgorithm($algorithm)

{  return $algorithm->sort($this->_a);

}}

$array = array('white', 'green', 'black', 'red');$sorter = new ArraySorter($a);$sorter->sortWithAlgorithm(new SelectionSort());$sorter->sortWithAlgorithm(new InsertionSort());

Strategy: example with Lazy Instantiation

Page 112: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 112/120

gy p y

Simone Carletti, Altura Labs

class ArraySorter {  protected $_a;  public function __construct($a)

{  $this->_a;  return self;

}  public function sortWithAlgorithm($algorithm)

{  require_once $algorithm;  $sorter = new $algorithm();  return $sorter->sort($this->_a);

}}

$array = array('white', 'green', 'black', 'red');$sorter = new ArraySorter($a);$sorter->sortWithAlgorithm('SelectionSort');$sorter->sortWithAlgorithm('InsertionSort');

Strategy: in the wild

Page 113: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 113/120

gy

Simone Carletti, Altura Labs

  Zend_Pdf_Resource_Image_Png allows different image

compression strategies (work in progress)

  Symfony enables you to configure different escaping strategieswith the escaping_strategy variable in your configuration file

Strategy: using & abusing

Page 114: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 114/120

gy

Simone Carletti, Altura Labs

  Make sure you are not coupling the context with a specific strategy

  Be careful when using one strategy as the default one

Time is running out… 

Page 115: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 115/120

g

Simone Carletti, Altura Labs

… but there are many other interesting Design Patterns out of there.

  Registry

  Mock Object

  Command  Decorator 

  Chain or Responsibility

  Data Mapper 

  Active Record

  Table Data Gateway and Row Data Gateway

Page 116: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 116/120

Beyond this Presentation

Simone Carletti, Altura Labs

Literature

Page 117: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 117/120

Simone Carletti, Altura Labs

Readings

Page 118: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 118/120

  http://www.fluffycat.com/PHP-Design-Patterns/

  http://www.phppatterns.com/

  http://www.devarticles.com/c/a/PHP/Introduction-to-Design-Patterns-Using-PHP/

  http://www.ibm.com/developerworks/library/os-php-designptrns/

  http://www.phplibrairies.com/tutorial_design-pattern_en.html

Simone Carletti, Altura Labs

Page 119: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 119/120

Q & A

(part 2/2)

Simone Carletti, Altura Labs

Page 120: Design Patterns 090322101222 Phpapp02

8/3/2019 Design Patterns 090322101222 Phpapp02

http://slidepdf.com/reader/full/design-patterns-090322101222-phpapp02 120/120

Thank you!

[email protected]

www.simonecarletti.com

Slides will be available at

www.slideshare.net/weppos