There are six principles of design patterns

  • Open Closure principle: a software entity such as classes, modules, and functions should be open for extension and closed for modification.

  • Richter’s substitution rule: all references to a base class must transparently use objects from its subclasses.

  • Dependency inversion principle: a high-level module should not depend on a low-level module, but both should depend on its abstraction; Abstraction should not depend on details; Details should depend on abstractions.

  • Single responsibility principle: Do not have more than one reason for a class change. In layman’s terms, a class has only one responsibility.

  • Interface isolation principle: a client should not rely on interfaces it does not need; The dependency of one class on another should be based on the smallest interface.

  • Demeter’s law: One object should know the least about the other.

1. Singleton

The singleton pattern means that at most one instance of the class exists in the application, and once created, it remains in memory forever!

Application Scenarios:

The singleton design pattern is often used in database class design. The singleton pattern is used to connect the database only once to avoid opening multiple database connections.

A singleton class should have the following characteristics:

A singleton class cannot be instantiated directly, but can only be instantiated by the class itself. Therefore, to achieve this restriction, the constructor must be marked private to prevent the class from being instantiated.

A private static member variable is required to hold the class instance and to expose a public static method that can access the instance.

In PHP, it is also common to provide an empty private __clone() method to prevent others from cloning instances of a singleton class.

Examples of singleton patterns:

<? php /** * Singleton of Database */ class Database { // We need a static private variable to store a Database instance. privatestatic $instance; // Mark as private to prevent it from being instanced. private function__construct() { // Do nothing. } private function__clone() { // Do nothing. } public static function getInstance() { if (! (self::$instance instanceof self)) { self::$instance = new self(); } return self::$instance; } } $a =Database::getInstance(); $b =Database::getInstance(); // true var_dump($a === $b);Copy the code

Ii. Factory design mode

When the parameters of the operation class change, only the corresponding factory class can be changed

The factory design pattern is often used to create an instance that is specifically used to instantiate and return its corresponding class, depending on input parameters or application configuration.

Use scenario: Use method new to instantiate the class, each instantiation only need to call the method in the factory class to instantiate.

Advantages: Because a class can be instantiated in many places. When the class name or parameter changes, the factory mode can be easily and quickly changed in a method under the factory class, avoiding the need to modify the instantiated object one by one.

For example, if rectangles and circles have the same method, then when we use the API provided by the base class to create instances, we automatically create instances of the corresponding classes by passing parameters, and they have the function to obtain perimeters and areas.

example

<? php interface InterfaceShape { function getArea(); function getCircumference(); } /** * Rectangle implements InterfaceShape {private $width; private $height; public function __construct($width, $height) { $this->width = $width; $this->height = $height; } public function getArea() { return $this->width* $this->height; } public function getCircumference() { return 2 * $this->width + 2 * $this->height; } /** * implements InterfaceShape {private $implements; function __construct($radius) { $this->radius = $radius; } public function getArea() { return M_PI * pow($this->radius, 2); } public function getCircumference() { return 2 * M_PI * $this->radius; Public static function create() {switch (func_num_args()) {case1: return newCircle(func_get_arg(0)); case2: return newRectangle(func_get_arg(0), func_get_arg(1)); default: # code... break; } } } $rect =FactoryShape::create(5, 5); // object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) } var_dump($rect); echo "<br>"; // object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) } $circle =FactoryShape::create(4); var_dump($circle);Copy the code

3. Observer design mode

The observer pattern is a very common design pattern. When used properly, it will bring great convenience to the program. When used improperly, it will give the next person an idea that is difficult to maintain.

Usage scenario: user login, need to write log, send points, participate in activities and so on using message queue, the user and log, points, activities decoupling

** What is observer mode? ** An object makes itself observable by providing methods that allow another object, the observer, to register itself. It sends messages to registered observers when observable objects change. The actions these observers perform with this information are independent of the observable object. The result is that objects can talk to each other without having to understand why. Observer mode is a kind of event system, which means that this mode allows one class to observe the state of another class. When the state of the observed class changes, the observing class can receive notification and make corresponding actions. The observer pattern allows you to avoid tight coupling between components. Look at the following examples and you’ll see!

<? Function onListen($sender, $args); function getObserverName(); } // Interface InterfaceObservable {function addObserver($observer); function removeObserver($observer_name); } // abstract class Observer implements InterfaceObserver {protected $observer_name; function getObserverName() { return $this->observer_name; } function onListen($sender, $observers) {}} // Abstract class Observable implements InterfaceObservable {protected $observers = array(); public function addObserver($observer) { if ($observerinstanceofInterfaceObserver) { $this->observers[] = $observer; } } public function removeObserver($observer_name) { foreach ($this->observersas $index => $observer) { if ($observer->getObserverName() === $observer_name) { array_splice($this->observers, $index, 1); return; }}}} // class A extends Observable {public function addListener($Listener) {foreach ($this->observersas)  $observer) { $observer->onListen($this, $listener); Class B extends Observer {protected $observer_name = 'B'; public function onListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; Class C extends Observer {protected $observer_name = 'C'; public function onListen($sender, $args) { var_dump($sender); echo "<br>"; var_dump($args); echo "<br>"; } } $a = new A(); $a->addObserver(new B()); $a->addObserver(new C()); $a->addListener('D'); $a->removeObserver('B'); // Print information:  // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } // string(1) "D" // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } // string(1) "D"Copy the code

4. Adapter mode

By transforming the interface of one class into another interface that the customer wants, the adapter pattern enables classes that would otherwise not work together due to interface incompatibations to work together.

Application scenario: The old code interface does not meet the new interface requirements, or the code is too messy to modify, or the third-party class library is used.

For example: PHP to connect to the database method: mysql,mysqli, pDO, can use the adapter unified

Class User {private $name; function __construct($name) { $this->name = $name; } public function getName() { return $this->name; Function getUserName(); } class UserInfo implements UserInterface { protected $user; function __construct($user) { $this->user = $user; } public function getUserName() { return $this->user->getName(); } $olduser = new User(' olduser '); echo $olduser->getName()."n"; $newuser = new UserInfo($olduser); echo $newuser->getUserName()."n";Copy the code

5. Strategic mode

Encapsulate a specific set of behaviors and algorithms into classes that are appropriate for some particular context.

Usage scenario: Personal understanding, policy pattern is the basis of dependency injection, inversion of control

For example: an e-commerce website system, for male and female users to jump to different categories of goods, and all advertising display different advertising

MaleUserStrategy.php

<? php namespace IMooc; class MaleUserStrategy implements UserStrategy { function showAd() { echo "IPhone6"; } function showCategory() {echo ""; }}Copy the code

FemaleUserStrategy.php

<? php namespace IMooc; Class FemaleUserStrategy implements UserStrategy {function showAd() {echo "2014新 女 人 "; } function showCategory() {echo ""; }}Copy the code

UserStrategy.php

<? php namespace IMooc; interface UserStrategy { function showAd(); function showCategory(); } <? php interface FlyBehavior{ public function fly(); } class FlyWithWings implements FlyBehavior{ public function fly(){ echo "Fly With Wings \n"; } } class FlyWithNo implements FlyBehavior{ public function fly(){ echo "Fly With No Wings \n"; } } class Duck{ private $_flyBehavior; public function performFly(){ $this->_flyBehavior->fly(); } public function setFlyBehavior(FlyBehavior $behavior){ $this->_flyBehavior = $behavior; } } class RubberDuck extends Duck{ } // Test Case $duck = new RubberDuck(); / / $duck->setFlyBehavior(new FlyWithWings()); $duck->performFly(); / / $duck->setFlyBehavior(new FlyWithNo()); $duck->performFly();Copy the code

Six, decorator mode

Use scenario: When a function or method draw, to meet different functional requirements, can use decorator mode; Build addDecorator in the method class,beforeDraw,afterDraw 3 new methods, place the last 2 at the beginning and end of the method draw to be modified. Then create different loader classes (with the same beforeDraw,afterDraw methods) that can be added with addDecorator and then looped in beforeDraw,afterDraw, somewhat similar to observer mode

  1. Decorator patterns that dynamically add the ability to modify classes

  2. A class provides a function, and if you want to modify and add additional functions, the traditional programming model requires that you write a subclass to inherit it and re-implement the class’s methods

  3. With the decorator pattern, you can achieve maximum flexibility by simply adding a decorator object at run time

DrawDecorator.php

<? php namespace IMooc; interface DrawDecorator { function beforeDraw(); function afterDraw(); }Copy the code

Canvas.php

<? php namespace IMooc; class Canvas { public $data; protected $decorators = array(); //Decorator function init($width = 20, $height = 10) { $data = array(); for($i = 0; $i < $height; $i++) { for($j = 0; $j < $width; $j++) { $data[$i][$j] = '*'; } } $this->data = $data; } function addDecorator(DrawDecorator $decorator) { $this->decorators[] = $decorator; } function beforeDraw() { foreach($this->decorators as $decorator) { $decorator->beforeDraw(); } } function afterDraw() { $decorators = array_reverse($this->decorators); foreach($decorators as $decorator) { $decorator->afterDraw(); } } function draw() { $this->beforeDraw(); foreach($this->data as $line) { foreach($line as $char) { echo $char; } echo "<br />\n"; } $this->afterDraw(); } function rect($a1, $a2, $b1, $b2) { foreach($this->data as $k1 => $line) { if ($k1 < $a1 or $k1 > $a2) continue; foreach($line as $k2 => $char) { if ($k2 < $b1 or $k2 > $b2) continue; $this->data[$k1][$k2] = ' '; }}}}Copy the code

ColorDrawDecorator.php

<? php namespace IMooc; class ColorDrawDecorator implements DrawDecorator { protected $color; function __construct($color = 'red') { $this->color = $color; } function beforeDraw() { echo "<div style='color: {$this->color}; '> "; } function afterDraw() { echo "</div>"; }}Copy the code

index.php

<? php define('BASEDIR', __DIR__); include BASEDIR.'/IMooc/Loader.php'; spl_autoload_register('\\IMooc\\Loader::autoload'); $canvas = new IMooc\Canvas(); $canvas->init(); $canvas->addDecorator(new \IMooc\ColorDrawDecorator('green')); $canvas - > the rect (3,6,4,12); $canvas->draw();Copy the code

Pay attention and don’t get lost

All right, everybody, that’s all for this article. All the people here are talented. As I said before, there are many technical points in PHP, because there are too many, it is really difficult to write, you will not read too much after writing, so I have compiled it into PDF and document, if necessary

Click on the code: PHP+ “platform”

As long as you can guarantee your salary to rise a step (constantly updated)

I hope the above content can help you. Many PHPer will encounter some problems and bottlenecks when they are advanced, and they have no sense of direction when writing too many business codes. I have sorted out some information, including but not limited to: Distributed architecture, high scalability, high performance, high concurrency, server performance tuning, TP6, Laravel, YII2, Redis, Swoole, Swoft, Kafka, Mysql optimization, shell scripting, Docker, microservices, Nginx, etc