Laravel Design Patterns 2.0
Bobby Bouwmann

Three more design patterns, extending from a Laracon EU talk two years ago

Level 50 on Laracasts!

Works at Enrise

Let's talk design patterns!

"What are design patterns?" Solutions for commonly-occurring problems. Building blocks

Laravel has a lot of design patterns (e.g. factory, presenter, singleton, bridge, repository)

Last year, spoke about Factory, Builder and another that I missed

Today, Singleton, Observer, Bridge patterns

Singleton Pattern

This is a creational pattern. You don't care about how it's created, just that it IS created.

Start with an example. Examples are going to be food-based..."raise your hands if you've made a pizza. raise your hands if you use a new oven every time you make a pizza"

"Every bite, you use a knife and fork. You don't get a new knife and fork for every bite"

Ensure that a class has only one instance, provides global access to that instance

Saves on system resources, share data.

Example is class PizzaOven. Only need one pizza oven!

How is it used in Laravel? DatabaseServiceProvider for db.factory/ConnectionFactory, db/DatabaseManager. Laravel handles it for us. DatabaseManager class doesn't indicate that it's a singleton

In Illuminate/Container/Container.php, singleton binds abstract, concrete, and shared (true)

If concrete isn't a closure, concrete is the closure given the abstract and concrete

Abstract binding is an array

When resolving an abstract thing in the container, Get the alias, and if it's already set, then return it. Otherwise, gets a concrete, instantiate an instance, register as a singleton, then return the object

Another example: LogServiceProvider

When you use dependency injection, it asks if the class already exists, and if not, it creates it and gets you squared away

Observer Pattern

AKA publish/delegation patterns

Increases communication between objects

Examples:

Defines a one-to-many dependency between objects so that when one object's state changes, all its dependents' listeners (subscribers) are notificated and updated automatically

Observable (the subject) and Observer (the listener)

<uml diagram describing Observable interface with observers and add/notify methods>

StartProcessOrder. add pushes a new observer, notify loops through the observers and calls their update method

We've probably already seen this when using events and listeners

$orderProcess = new StartProcessOrder();
$orderProcess->add(new SendDeliveryTime());
$orderProcess->add(new NotifyBaker());

$orderProcess->notify();

In Laravel, EventServiceProvider has a listen property with keys as events and value arrays as what should get processed

Dispatcher clause has listen function with events and listener. Handles wildcard listen calls!

Stores callback in container. Laravel stores in container, so also Singleton!

How does Laravel trigger this when something happens? We have an event helper (or can call dispatch)

// Example
event(new Registered($user));

Also used for model events (e.g. creating, created, updated), uses that same dispatch clause

Bridge Pattern

This is a structural pattern, describes inheritance and relationships between objects. Solves complex composition

Examples:

They're unique, but they can work together or independently

Decouples an abstraction from its implementation so that the two can vary independently

UML:

Pizza and ChickenWings can have their own methods.

Promotion the abstract class exposes applyDiscount(float $Price), while each promotion calculates

$product = new ChickenWings(new BlackFriday, 12.50, 'Wings');
$product->applyDiscount();

How does Laravel use it? Migrations!

MysqlBuilder implements Builder

MySqlGrammar, SqlServerGrammar, PostgresGrammar, SqliteGrammar all implement Grammar (compileTableExists, compileEnableForeignKeyConstraints)

Builder.php constructor sets grammar by getSchemaGrammar() on the passed-in connection

Builder may throw a LogicException in its method of dropAllTables, but MyqlBuilder can override that with its own implementation. SQLiteBuilder can have its own.

Looks like Adapter pattern, but bridge pattern is designed up-front to let the abstraction and implementation vary independently.

Recap:

No silver bullet, learn by doing and trying

Writing a book! laravelsecrets.com @stefanbauerme @bobbybouwmann