Skip to content
O'Reilly Media | Head First Design Patterns Book | PHP Examples
PHP
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
ch01
ch02/Weather-O-Rama
ch03
ch04
ch05/Choc-O-Holic adapter Oct 21, 2018
ch06 command pattern more flex & start with state pat Dec 2, 2018
ch07
ch08/StarbuzzCoffeeRecipe
ch09
ch10
.editorconfig
.gitignore
README.md

README.md

Head-First-Design-Patterns-PHP

Head First Design Patterns : A Brain-Friendly Guide book examples code in PHP


The original code in the book is in java.

I chose this book because it has a really unique way of describing things and making them easy to understand maybe somebody else will find it useful.


Run the code

First you have to generate the auto loader with composer

note: do this step for each file that have composer.json

All examples are tested with php7.2

$ composer dump-autoload


Notes index


MY-NOTES


chapter 1: Strategy Pattern

aka Policy Pattern

Defines a set of encapsulated algorithms that can be swapped to carry out a specific behavior.

Strategy pattern used when

Strategy pattern is used when we have multiple algorithms for specific task and the client decides the actual implementation to be used at runtime.

  • encapsulate what change and you will have flexible system.

  • separate the code that will be changed.

  • Program to an interface not an implementation : an interface in this context could also refers to an abstract class or class that implements particular behavior

  • Represent the behavior of things and not the thing.

  • Think of behaviors as a set of algorithms.

  • Composition over inheritance.

  • ShoppingCart example is not from the book


chapter 2: Observer Pattern

aka Pub/Sub

According to GoF, observer design pattern intent is;

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Observer used when

State changes in one or more objects should trigger behavior in other object one-to-many relationship between objects so that when one object changes state all it's dependents are notified and updated automatically.

PHP provides Stander PHP Library (SPL) Observer Pattern through SplObserver interface and SplSubject interface

Model-View-Controller (MVC) frameworks also use Observer pattern where Model is the Subject and Views are observers that can register to get notified of any change to the model.

  • best usage when there's single source of truth one object with many unknown dependents

  • This single source of truth is an Object's state that's many objects care of knowing it.

  • defines one-to-many relationship between objects.

  • the Publisher aka the Subject updates the observer using common interface.

  • the Subscribers aka the Observers are loosely coupled and the subject no nothing about then except that they are implement the observer interface.

  • STRIVE FOR LOOSELY COUPLE DESIGN BETWEEN OBJECT THAT INTERACT.


chapter 3 : Decorator Pattern (Design Eye for The Inheritance Guy)

Allows for the dynamic wrapping of objects in order to modify their existing responsibilities and behaviors.

Attach additional responsibilities to an object dynamically. Provide a flexible alternative to sub-classing for existing functionality.

Decorator used when

Decorator pattern is best used when we introduced to existing code that we want to extend its functionality.

since decorators are basically wrappers around objects the PHP I/O classes same as Java uses decorator pattern to add more functionality to the stream to read more Wrappers in php and you can even register a custom wrapper (decorators) to add your own filter/wrapper to I/O stream see this example.

  • Decorator reduce the chance of bugs and side effects in legacy code .

  • Decorator it gives the object new responsibility dynamically at runtime using composition .

  • It follows the open-close principle .

  • General speaking design patterns add abstraction level that's add complexity to code that's way we should always use it on the parts that change and overusing it .

  • In other words ALWAYS IDENTIFY WHAT CHANGES.

  • Again ALWAYS IDENTIFY WHAT's GOING TO CHANGE.

  • Decorators must have the same super-class as the object they decorate.

  • FAVOR COMPOSITION OVER INHERITANCE .

  • Inheritance makes static behavior but Composition make the behavior dynamic and it can change at runtime .


chapter 4 : The Factory pattern

Factory method , Abstract factory , Dependency Inversion ?

The Factory Method Pattern

The Factory Method Patter defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Factory-method

    +----------------------+
    |      PizzaStore      |
    +----------------------+ <- abstract class defines
    |                      | abstract factory method `createPizza()`
    |    createPizza()     | that lets the sub-class decide for it.
    |                      |
    |    orderPizza()      |                         <abstract product>
    |                      |                             +-------+
    +-----^--------------^-+                             | Pizza |<-------+
          |              |                               +-^-----+        |
          |              |                                 |              |
          |              |                                 |              |
          |              |                                 |              |
          |              |                                 |              |
          |              |                                 |              |
+---------+------+      ++-----------------+      +------------------+    |
| NYPizzaStore   |      |ChicagoPizzaStore |      |ChicagoCheesePizza|    |
+----------------+      +------------------+      +--------^---------+    |
|  createPizza() |      |  createPizza()   |               |              |
|                |      |                  +--<creates>----+              |
+-------------+--+      +------------------+                              |
<creator>     |              <creator>            +-------------+         |
              +---------------------<creates>---->|NYCheesePizza|---------+
                                                  +-------------+

Factory Method Pattern used when

When a client doesn't know what concrete classes it will be required to create at runtime, but just wants to get a class that will do the job.


Dependency Inversion Principle

Depend upon abstractions. Do not depend upon concrete classes.


  • You should Depend upon abstraction Not upon an implementation .

  • High-level components should not depend on low-level components they should both depend on abstractions.

  • Instantiation is an activity that should not be in public and can often lead to coupling problems.

  • new keyword === an Implementation (not an Interface).

  • IDENTIFY WHAT CHANGES.

  • Factories (encapsulate) handle details of object creation.

  • Factory method relays on inheritance and delegates the object creation to subclasses which implements the factory method and create concrete objects.

  • Factory method lets subclasses decide what class instantiate not because it allows rather than it does not know the product .

  • Strive for guidelines The following guidelines can help you avoid OO designs that violate the Dependency Inversion Principle :

  1. No variable should hold reference for a concrete class. If you use new you’ll be holding a reference to a concrete class. Use a factory to get around that

  2. No class should derive form concrete class. If you derive from a concrete class, you’re depending on a concrete class. Derive from an abstraction, like an interface or an abstract class

  3. No method should override method on base class if so then the base class not really an abstraction. If you override an implemented method, then your base class wasn’t really an abstraction to start with. Those methods implemented in the base class are meant to be shared by all your subclasses.


Abstract Factory Pattern

Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Abstract Factory Pattern used when

it's used to construct objects such that they can be decoupled from the implementing system. The pattern is best utilized when your system has to create multiple families of products or you want to provide a library of products without exposing the implementation details.

  • The methods of the abstract factory are often FACTORY METHODS.

Abstract-Factory


  • The job of an Abstract Factory is to define an interface for creating a set of products.

  • Abstract factory and Factory method are both great in terms of decoupling application from specific implementation.

  • Factory method uses Classes (inheritance).

  • Abstract Factory uses Objects (objects composition).


chapter 5 : Singleton

The singleton pattern ensures a class has only one instance and provide global access to it .

Singleton Pattern used when

for anything (object) that unique.

Singletons are used a lot where you need to provide a registry, or something like a thread pool. Logging is also another popular use of Singletons, providing one single access point to an applications log file.


chapter 6 : Command Pattern

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

The command pattern used when

it's used to manage algorithms , relationships and responsibilities between objects.

  1. When history of requests is needed.
  2. You need a callback functionality.
  3. Requests need to handled at variant times or in variant order.
  4. The invoker should be decoupled from the object handling the invocation.
  • Decouples the requester of an action from it's preformer.
  • command pattern encapsulate requests as objects .
  • The client will never bother about the how and the what commands will actually do.
  • The Bank Transaction example is not from the book
  • The command pattern forwards the request to a specific moudle.

The Adapter and The Facade Patterns

Adapter Pattern

aka Wrapper Pattern

The Adapter Pattern converts the interface of a class into another interface the client expects. Adapters lets classes work together that couldn't otherwise because of incompatible interfaces.

Adapter Pattern used when

When a class that you need to use doesn't meet the requirements of an interface. Exposed to legacy code may encounter an old interface needs to be converted to match new client code Adapters allows programming components to work together that otherwise wouldn't because of mismatched interfaces.

Adapter pattern motivation is that we can reuse existing software if we can modify the interface.

There are two kinds of Adapters

  1. Class Adapter uses inheritance [multiple inheritance] *not supported in java nor php. can only wrap a class It cannot wrap an interface since by definition it must derive from some base class.

  2. Object Adapter uses Object composition composition and can wrap classes or interfaces, or both. It can do this since it contains, as a private, encapsulated member,the class or interface object instance it wraps.

"Because inheritance exposes a subclass to details of its parent's implementation, it's often said that 'inheritance breaks encapsulation'". (Gang of Four 1995:19)

  • DON'T MIX DECORATORS WITH ADAPTERS THEY'RE BOTH WRAPPERS BUT DECORATORS ADD NEW RESPONSIBILITIES WHILE ADAPTERS CONVERT AN INTERFACE.

Facade Pattern

The Facade Pattern provides a unified interface to a set of interfaces in subsystem. Facade defines a higher-level interface that make the subsystem easier to use.

Facade used when

when you want to simplify a complex system.
  • Facades don't encapsulate .

  • Facade Pattern allows to avoid tight coupling between client and subsystem.

  • Design Principle Principle of Least Knowledge - talk only to your immediate friends. {Least Knowledge principle} aka Law of Demeter

Least Knowledge principle guidelines :

  • take any object.
  • from any method on that object we should only instantiate :
    • The object itself.
    • Objects passed as a parameter to the method.
    • Any object the method creates or instantiate.
    • Any components of the object by instance variable has-A-relationship.
    • NOT TO CALL METHODS ON OBJECTS THAT WERE RETURNED FROM ANOTHER METHODS!.

$Q = "What’s the harm in calling the method of an object we get back from another call?"

$A = "if we were to do that, then we’d be making a request
of another object’s subpart (and increasing the number of objects
we directly know). In such cases, the principle forces us to ask
the object to make the request for us; that way we don’t have
to know about its component objects
(and we keep our circle of friends small)."

Without the principle


public function getTemp() : float {
    $thermometer = $this->station->getThermometer();
    //we get thermometer OBJECT for
    //the station then we call get temperature
    return $thermometer->getTemperature();
}

With Least Knowledge principle


public function getTemp() : float {
    //we add a method to the station class with
    //that we reduce the number of classes we're dependent on
    return $this->station->getTemperature();
}

Wrappers

PATTERN INTENT
Decorator Doesn't alter the interface but adds responsibilities.
Adapter converts one interface to another.
Facade Makes an interface simpler.

Template Method Pattern [Encapsulating Algorithms]

Template Method Pattern

aka Hollywood pattern

The Template Method Pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

It's all about creating Template form an Algorithm


$q =  "What's a `Template` ?"

$a = "it's just a method that defines an algorithm as steps"

Hooked on Template

A Hook is a method that declared in the abstract class but given an empty on default implementation ; giving the subclass the ability to hook into override the algorithm on various points.

When to use what ? abstract methods VShooks. use abstract methods when the implementation is a MUST in the subclass. for the hooks it's optional for the subclass.

Hollywood Principle

Don't call us, we'll call you.

  • Hollywood principle helps prevents Dependency rot. huh ..what!?

  • Dependency rot: it's bad and a mess ! it's when high-level components depending on low-level components depending on high-level components ...and so on. it's hard to understand system with such a flaw.

  • Hollywood principle : is a Technique for building frameworks or components so that low-level components can be Hooked into the computation without creating dependency between the low-level components and high-level components.

  • Hollywood principle guides us to put decision-making in high-level modules that can decide how and when to call low level modules.

  • The Factory Method is a specialization of Template Method

Who does what ?

Pattern Description
Template Method Subclasses decide how to implement steps in an algorithm.
Strategy Encapsulate interchangeable behavior and use delegation to decide which behavior to use.
Factory Method Subclasses decide which concrete classes to create.

Bounce

another great example from journaldev

to understand the method template pattern

suppose we want to provide an algorithm to build a house. The steps need to be performed to build a house are – building foundation, building pillars, building walls and windows. The important point is that the we can’t change the order of execution because we can’t build windows before building the foundation. So in this case we can create a template method that will use different methods to build the house.

Template Method Pattern used when

  • Template Methods are frequently used in general purpose frameworks or libraries that will be used by other developer.
  • When the behavior of an algorithm can vary but not the order.
  • When there's a code duplication this is always gives a clear sign of bad design decisions and there's always room for improvement.

The Iterator and Composite Patterns [Well-Managed Collection]

Iterator Pattern

The Iterator Pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

  • Iterator provide a standard way common interface to traverse through a group of Objects aggregate.
  • Iterator allows access to an aggregate's elements without exposing its internal structure.

checkout iterator branch for iterator implementation

$ git checkout iteratorPattern
Switched to branch 'iteratorPattern'

iterator

  • The Aggregate defines an interface for the creation of the Iterator object.
  • The ConcreteAggregate implements this interface, and returns an instance of the ConcreteIterator.
  • The Iterator defines the interface for access and traversal of the elements, and the ConcreteIterator implements this interface while keeping track of the current position in the traversal of the Aggregate.

Iterator used when

  • When you need access to elements in a set without access to the entire representation.
  • When you need a uniform traversal interface, and multiple traversals may happen across elements.

implementations notes

Unlike java , PHP Array can be treated as an array, list, hash-table, stack, queue, dictionary, collection,...and probably more.

The original example uses both Java Array and ArrayList.

PHP implementation specifics

For the sake of Objectville example :

  • I will use SplFixedArray to mimic (static)fixed size arrays.
  • We will ignore the fact that both normal php array and SplFixedArray implement the Traversable interface and that both can be easily traversed using a foreach.
  • You cannot implement Traversable interface it's an abstract base interface, you can't implement it alone but you can implement interfaces called Iterator or IteratorAggregate By implementing either of these interfaces you make a class iterable and traversable using foreach
  • For the sake of this example we're going to make our own interface and we call it IteratorInterface.

Single Responsibility Principle (SOLID)

A Class should have only one reason to change.

Separating responsibilities in design is one of the most difficult things to do, to succeed is to be diligent in examining your designs and watchout for signals that a class is changing in more than one way as your system grows.

We should strive to assign only one responsibility to each class.


The Composite Pattern

The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Composite


The << Component >> abstract class define all objects in composed system.
The Leaf has no children.
The Composite contains components.

  • Composite pattern comes into play when developing a system where a component could either be an individual object or a representation of a collection of objects.

  • Composite pattern provides a structure to hold both individual objects an composites.

  • A Component is any object in a Composite structure.

  • Components may be other composites or leaf nodes.

  • Remember to balance transparency and safety.

Is Composite Pattern really follow the single responsibility principle

The Composite Pattern

  1. manages a hierarchy

  2. performs operations related to Menus

that's 2 responsibilities.

The Composite Pattern trades Single Responsibility Principle for transparency

Transparency: Since the Composite interface contain child management operations and the leaf (items non iterable) operations The client can treat both the composites and leaf nodes uniformly, both are transparent to the client.

Having both operations in the Component class will cause a bit loss of safety because the client might try to do Composite related operation e.g add to a leaf item which is invalid.

Composite Pattern used when

  • Graphics frameworks are the most common use of this pattern.
  • The Composite pattern is frequently used for abstract syntax tree representations.
  • when dealing with tree structures Anything that can be modelled as a tree structure can be considered an example of Composite.
  • when you have collection of objects with whole-part relationships and you want to be able to treat those objects uniformly.

what's whole-part relationships ?

also known as aggregation relationship it's a relationship between two classes in which one represent the larger class (whole) that consists of smaller classes (parts)


  • We call components that contain other components composite objects and components that don't contain other components leaf objects.

  • By treating objects uniformly that means there's a common methods can be called on both composite or leaf that implies that both must have the same interface.


Who does what ?

Pattern Description
Strategy Encapsulate interchangeable behavior and use delegation to decide which behavior to use.
Adapter Changes the interface of one or more classes.
Iterator Provides a way to traverse a collection of objects without exposing the collection's implementation.
Facade Simplifies the interface of a group of classes.
Composite Clients treat collections of objects and individual objects uniformly.
Observer Allow a group of objects to be notified when some state changes.

chapter 10: The State Pattern *The State of Things*

Allows an object to alter its behaviour when its internal state changes. The object will appear to change its class.


State

  • The Context have number of internal states.
  • The State << interface >> defines a common interface for all concrete states.
  • Each Behavior correspond with ConcreteState implements its own logic for the request.
  • When Context changes state a different ConcreteState associate with it.
  • Simply change the state object in context to change the behavior.

This is similar to Strategy Pattern except changes happens internally rather than the client deciding the strategy.

key-points: Think of Strategy Pattern as a flexible alternative to sub-classing. Think of State Pattern as an alternative to putting lots of conditionals.

State Pattern used when

  • You need a class to behave differently based on some condition.
  • If you are using if-else condition block to perform different actions based on the state.

Who does what ?

Pattern Description
State Encapsulate state-based behavior and delegate behavior to the current state.
Strategy Encapsulate interchangeable behavior and use delegation to decide which behavior to use.
Template Method Subclasses decide how to implement steps in an algorithm.

You can’t perform that action at this time.