Explore a comprehensive reference cheat sheet for classic and modern design patterns in PHP, complete with UML diagrams, concise descriptions, and guidelines for selecting the right pattern.
Welcome to the Pattern Reference Cheat Sheet, your quick guide to understanding and implementing design patterns in PHP. This section provides concise summaries, UML diagrams, and practical advice on when to use each pattern. Let’s dive into the world of design patterns and enhance your PHP development skills.
classDiagram
class Singleton {
-Singleton instance
-Singleton()
+getInstance() Singleton
}
1class Singleton {
2 private static $instance;
3
4 private function __construct() {
5 // Private constructor to prevent instantiation
6 }
7
8 public static function getInstance() {
9 if (self::$instance === null) {
10 self::$instance = new Singleton();
11 }
12 return self::$instance;
13 }
14}
classDiagram
class Creator {
<<abstract>>
+factoryMethod() Product
}
class ConcreteCreator {
+factoryMethod() Product
}
class Product {
<<interface>>
}
class ConcreteProduct {
}
Creator <|-- ConcreteCreator
Product <|-- ConcreteProduct
Creator --> Product
1interface Product {
2 public function operation();
3}
4
5class ConcreteProduct implements Product {
6 public function operation() {
7 return "ConcreteProduct operation";
8 }
9}
10
11abstract class Creator {
12 abstract public function factoryMethod(): Product;
13
14 public function someOperation() {
15 $product = $this->factoryMethod();
16 return $product->operation();
17 }
18}
19
20class ConcreteCreator extends Creator {
21 public function factoryMethod(): Product {
22 return new ConcreteProduct();
23 }
24}
classDiagram
class AbstractFactory {
<<interface>>
+createProductA() ProductA
+createProductB() ProductB
}
class ConcreteFactory1 {
+createProductA() ProductA
+createProductB() ProductB
}
class ProductA {
<<interface>>
}
class ProductB {
<<interface>>
}
class ConcreteProductA1 {
}
class ConcreteProductB1 {
}
AbstractFactory <|-- ConcreteFactory1
ProductA <|-- ConcreteProductA1
ProductB <|-- ConcreteProductB1
AbstractFactory --> ProductA
AbstractFactory --> ProductB
1interface AbstractFactory {
2 public function createProductA(): ProductA;
3 public function createProductB(): ProductB;
4}
5
6class ConcreteFactory1 implements AbstractFactory {
7 public function createProductA(): ProductA {
8 return new ConcreteProductA1();
9 }
10
11 public function createProductB(): ProductB {
12 return new ConcreteProductB1();
13 }
14}
15
16interface ProductA {
17 public function operationA();
18}
19
20interface ProductB {
21 public function operationB();
22}
23
24class ConcreteProductA1 implements ProductA {
25 public function operationA() {
26 return "Operation A1";
27 }
28}
29
30class ConcreteProductB1 implements ProductB {
31 public function operationB() {
32 return "Operation B1";
33 }
34}
classDiagram
class Target {
+request()
}
class Adapter {
+request()
}
class Adaptee {
+specificRequest()
}
Target <|-- Adapter
Adapter --> Adaptee
1class Target {
2 public function request() {
3 return "Target request";
4 }
5}
6
7class Adaptee {
8 public function specificRequest() {
9 return "Adaptee specific request";
10 }
11}
12
13class Adapter extends Target {
14 private $adaptee;
15
16 public function __construct(Adaptee $adaptee) {
17 $this->adaptee = $adaptee;
18 }
19
20 public function request() {
21 return $this->adaptee->specificRequest();
22 }
23}
classDiagram
class Component {
<<interface>>
+operation()
}
class ConcreteComponent {
+operation()
}
class Decorator {
+operation()
}
class ConcreteDecorator {
+operation()
}
Component <|-- ConcreteComponent
Component <|-- Decorator
Decorator <|-- ConcreteDecorator
Decorator --> Component
1interface Component {
2 public function operation();
3}
4
5class ConcreteComponent implements Component {
6 public function operation() {
7 return "ConcreteComponent operation";
8 }
9}
10
11class Decorator implements Component {
12 protected $component;
13
14 public function __construct(Component $component) {
15 $this->component = $component;
16 }
17
18 public function operation() {
19 return $this->component->operation();
20 }
21}
22
23class ConcreteDecorator extends Decorator {
24 public function operation() {
25 return "ConcreteDecorator(" . parent::operation() . ")";
26 }
27}
classDiagram
class Subject {
+attach(Observer)
+detach(Observer)
+notify()
}
class ConcreteSubject {
-state
+getState()
+setState()
}
class Observer {
<<interface>>
+update()
}
class ConcreteObserver {
-subject
+update()
}
Subject <|-- ConcreteSubject
Observer <|-- ConcreteObserver
ConcreteObserver --> Subject
1interface Observer {
2 public function update($state);
3}
4
5class ConcreteObserver implements Observer {
6 private $state;
7
8 public function update($state) {
9 $this->state = $state;
10 echo "Observer state updated to: $state\n";
11 }
12}
13
14class Subject {
15 private $observers = [];
16 private $state;
17
18 public function attach(Observer $observer) {
19 $this->observers[] = $observer;
20 }
21
22 public function detach(Observer $observer) {
23 $key = array_search($observer, $this->observers, true);
24 if ($key !== false) {
25 unset($this->observers[$key]);
26 }
27 }
28
29 public function notify() {
30 foreach ($this->observers as $observer) {
31 $observer->update($this->state);
32 }
33 }
34
35 public function setState($state) {
36 $this->state = $state;
37 $this->notify();
38 }
39}
classDiagram
class Context {
+setStrategy(Strategy)
+executeStrategy()
}
class Strategy {
<<interface>>
+execute()
}
class ConcreteStrategyA {
+execute()
}
class ConcreteStrategyB {
+execute()
}
Context --> Strategy
Strategy <|-- ConcreteStrategyA
Strategy <|-- ConcreteStrategyB
1interface Strategy {
2 public function execute();
3}
4
5class ConcreteStrategyA implements Strategy {
6 public function execute() {
7 return "Strategy A executed";
8 }
9}
10
11class ConcreteStrategyB implements Strategy {
12 public function execute() {
13 return "Strategy B executed";
14 }
15}
16
17class Context {
18 private $strategy;
19
20 public function setStrategy(Strategy $strategy) {
21 $this->strategy = $strategy;
22 }
23
24 public function executeStrategy() {
25 return $this->strategy->execute();
26 }
27}
classDiagram
class Model {
+getData()
+setData()
}
class View {
+render()
}
class Controller {
+updateModel()
+updateView()
}
Model <--> Controller
View <--> Controller
1class Model {
2 private $data;
3
4 public function getData() {
5 return $this->data;
6 }
7
8 public function setData($data) {
9 $this->data = $data;
10 }
11}
12
13class View {
14 public function render($data) {
15 echo "Rendering data: $data\n";
16 }
17}
18
19class Controller {
20 private $model;
21 private $view;
22
23 public function __construct(Model $model, View $view) {
24 $this->model = $model;
25 $this->view = $view;
26 }
27
28 public function updateModel($data) {
29 $this->model->setData($data);
30 }
31
32 public function updateView() {
33 $this->view->render($this->model->getData());
34 }
35}
Selecting the right design pattern depends on the problem you are trying to solve. Here are some guidelines:
Experiment with the code examples provided. Try modifying the classes and methods to see how changes affect the behavior of the patterns. For instance, in the Strategy pattern, create additional strategies and see how they can be swapped in and out of the context.
Understanding design patterns is easier with visual aids. Use UML diagrams to map out the relationships and interactions between classes and objects. This helps in grasping the structure and flow of each pattern.
For further reading on design patterns, consider these resources:
Remember, this is just the beginning. As you progress, you’ll build more complex and interactive PHP applications. Keep experimenting, stay curious, and enjoy the journey!