Analyze twenty-three design patterns

1. Classification of Design Patterns

Twenty-three design patterns, roughly divided into three categories:
five creational types:
singleton, factory, abstract factory, builder, prototype pattern
seven structural types:
adapter, decoration, bridging, combination, flyweight, proxy, Appearance mode
Eleven types of behavior:
command, state, chain of responsibility, interpreter, intermediary, visitor, strategy, memo, iterator, template, observer

2. Six principles of design patterns

1. Single Responsibility Principle

A class should have only one reason to change it.

2. Open-Closed Principle

Software entities (classes, modules, functions, etc.) should be extensible, but not modifiable.

3. Dependency Inversion Principle

A. High-level modules should not depend on low-level modules. Both should rely on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.

4. Liskov Substitution Principle

Subtypes must be able to replace their supertypes.

5. Law of Demeter = Principle of Least Knowledge

Two classes should not interact directly if they don't have to communicate directly with each other. If one of the classes needs to call a method of another class, the call can be forwarded by a third party.

6. Interface isolation

Establish a single interface
a. The client should not rely on the interface it does not need
b. The dependency between classes should be established on the smallest interface.
Next, we will code in PHP and start our journey of design patterns

Third, implement the design pattern

Creation type:

1. Singleton mode

UML
insert image description here
analysis
Singleton mode: Ensure that a class has only one instance, and provide a global access point to access it.
Some application resources are exclusive because there is exactly one resource of this type. For example, a connection to a database through a database handle is exclusive. You want to share the database handle across your application because it's an overhead when keeping a connection open or closed, more so when fetching a single page. The single-element pattern can satisfy this requirement. If the application contains one and only one object at a time, then this object is a single element (Singleton)
common form:

<?php
class Singleton {
    
    

    private static $new;                         //申请一个私有的静态成员变量来保存该类的唯一实例

    private function __construct() {
    
    }            //声明私有的构造方法,防止类外部创建对象

    public static function getInstance () {
    
          //声明一个静态公共方法,供外部获取唯一实例
        if (! (self::$new instanceof self)) {
    
    
                self::$new = new self;
        }
        return self::$new;
    }

    private function __clone() {
    
    }               //声明私有的克隆方法,防止对象被克隆

    public function __sleep() {
    
                     //重写__sleep方法,将返回置空,防止序列化反序列化获得新的对象
        return [];
    }
}

Thread safety:
lock is to ensure that when one thread is in the critical section of the code, another thread does not enter the critical section. If other threads try to enter the locked code, it will wait (i.e. be blocked) until the object is freed.

public static function getInstance () {
    
          //声明一个静态公共方法,供外部获取唯一实例
   //在这里加锁
    lock {
    
    
	    if (! (self::$new instanceof self)) {
    
    
	        self::$new = new self;
	    }
	}
    return self::$new;
}

Double lock:

public static function getInstance () {
    
          //声明一个静态公共方法,供外部获取唯一实例
    if (! (self::$new instanceof self)) {
    
        //线程安全
        lock {
    
    
	        if (! (self::$new instanceof self)) {
    
    
	            self::$new = new self;
	        }
        }
    }
    return self::$new;
}

2. Simple factory mode

UML
insert image description here
analysis:
Simple factory: It is a factory object that determines which instance of the product class to create. An instance of A calls a method of an instance of B, which is called A depends on B. If you use the new keyword to create a B instance (hard-coded coupling), then call the method of the B instance. Once the system needs to be refactored: when class C needs to be used instead of class B, the program has to rewrite class A code. With the factory pattern, you don't need to care about the implementation and creation process of the B object.
Advantages: Separate the caller of the object from the object creation process. When the object caller needs the object, he can directly request it from the factory. In this way, the hard-coded coupling between the caller of the object and the implementation class of the object is avoided, so as to improve the maintainability and scalability of the system.
Defect: When the product is modified, the factory class must also be modified accordingly, which violates the open-close principle. As in the above example, when multiplication needs to be added, the factory class OperationFactory needs to be modified. The
simple factory model is suitable for simple business cases or cases where specific products are rarely added.
Code display:

<?php
class Operation {
    
    
    private $_numberA = 0;
    private $_numberB = 0;

    public function getNumberA() {
    
    
        return $this->_numberA;
    }
    public function getNumberB() {
    
    
        return $this->_numberB;
    }

    public function setNumberA($value) {
    
    
        $this->_numberA = $value;
    }
    public function setNumberB($value) {
    
    
        $this->_numberB = $value;
    }

    public function getResult() {
    
     }
}

class OperationAdd extends Operation {
    
    

    public function getResult()
    {
    
    
        return $this->getNumberA() + $this->getNumberB();
    }
}

class OperationSub extends Operation {
    
    

    public function getResult()
    {
    
    
        return $this->getNumberA() - $this->getNumberB();
    }
}

class OperationFactory
{
    
    
    public function createOperate($operate)
    {
    
    
        $operator = new Operation();
        switch ($operate){
    
    
            case '+':
                $operator =  new OperationAdd();
                break;
            case '-':
                $operator =  new OperationSub();
                break;
        }
        return $operator;
    }
}
$factory  = new OperationFactory();
$add = $factory->createOperate('+');
$sub = $factory->createOperate('-');
$add->setNumberA(1);
$add->setNumberB(2);
echo $add->getResult();

3. Abstract factory pattern

UML
insert image description here
Analysis
The abstract factory pattern provides an interface for creating a series of related or interdependent objects without specifying their specific classes.
advantage:

  1. Easy to exchange product series, the specific factory class only appears once during initialization, it is easy to change the specific factory of an application.
  2. The specific process of creating an instance is separated from the client. The client operates the instance through their abstract interface. The specific class name of the product is also separated from the implementation of the specific factory and will not appear in the client code.
    Disadvantages:
    a. If you add items, you need to change the abstract interface and concrete factory class.
    Common writing - code display
<?php

class User
{
    
    

}
interface IUser
{
    
    
    public function Insert($user);
    public function getUser($userId);
}
class SqlServerUser implements IUser
{
    
    

    public function Insert($user)
    {
    
    
        echo 'SQL_SERVER插入';
    }

    public function getUser($userId)
    {
    
    
        echo 'SQL_SERVER获取';
    }
}

class MySQLUser implements IUser
{
    
    

    public function Insert($user)
    {
    
    
        echo 'MySQL插入';
    }

    public function getUser($userId)
    {
    
    
        echo 'MySQL获取';
    }
}

interface IFactory
{
    
    
    public function createUser();
}

class SqlServerFactory implements IFactory
{
    
    

    public function createUser()
    {
    
    
        return new SqlServerUser();
    }
}

class MySQLFactory implements IFactory
{
    
    

    public function createUser()
    {
    
    
        return new MySQLUser();
    }
}
$user = new User();
$factory = new MySQLFactory();
$IUser = $factory->createUser();     //创建User模型对象
$IUser->Insert($user);               //插入数据
$IUser->getUser(1);                  //获取数据

Reflection writing - code display

<?php
namespace dataAccess;

use ReflectionClass;
use ReflectionException;

interface IUser
{
    
    
    public function Insert();
    public function getUser();
}

class SqlServerUser implements IUser {
    
    

    public function Insert()
    {
    
    
        echo 'SQL_SERVER插入';
    }

    public function getUser()
    {
    
    
        echo 'SQL_SERVER获取';
    }
}

class MySQLUser implements IUser {
    
    

    public function Insert()
    {
    
    
        echo 'MySQL插入';
    }

    public function getUser()
    {
    
    
        echo 'MySQL获取';
    }
}

class DataAccessFactory {
    
    
    
    private  $db = 'SqlServer';
    public $namespace = 'dataAccess\\';

    public function __construct()
    {
    
    
        /**
         * 从配置项中获取 driver
         */
        $config = include 'data_access_config.php';
        $this->db = $config['driver'];
    }

    public  function createUser()
    {
    
    
        $className = $this->namespace . $this->db . 'User';
        try {
    
    
            $class = new ReflectionClass($className);
            $user = $class->newInstance();
        }catch (ReflectionException $exception) {
    
    
            throw new \InvalidArgumentException('暂不支持的数据库类型');
        }
        return $user;
    }
}
$data = new DataAccessFactory();
$sql = $data->createUser();
$sql->Insert();

4. Builder mode (generator mode)

UML
insert image description here
parses
the builder pattern, which separates the construction of a complex object from its representation, so that the same construction process can create different representations. Users only need to know the type of builder to get them, but the specific construction process and details do not need to know. Applicable to the construction order is usually stable, but the construction inside the object is often faced with complex changes.
code display

<?php

class Product                                   //产品类
{
    
    
    private $parts = array();

    public function add($part)
    {
    
    
        $this->parts [] = $part;
    }

    public function show()
    {
    
    
         echo "产品创建...\n";
        foreach ($this->parts as $key => $value)
        {
    
    
            var_dump($value);
        }
    }
}

abstract class Builder                          //抽象建造类
{
    
    
    abstract public function buildPartA();
    abstract public function buildPartB();
    abstract public function getResult();
}

class ConcreteBuilder extends Builder        //具体建造类
{
    
    
    private $product;
    function __construct()
    {
    
    
        $this->product = new Product();
    }

    public function buildPartA()
    {
    
    
        $this->product->add('部件A');
    }

    public function buildPartB()
    {
    
    
        $this->product->add('部件B');
    }

    public function getResult()
    {
    
    
        return $this->product;
    }
}
class Director
{
    
    
    public function Construct($builder)
    {
    
    
        $builder->buildPartA();
        $builder->buildPartB();
    }
}

$director = new Director();         //指挥者
$builder = new ConcreteBuilder();   //建造者
$director->Construct($builder);     //创建
$product = $builder->getResult();   //获取产品
$product->show();                   //展示  

5. Prototype mode

UML
insert image description here
parses
the prototype pattern, uses the prototype instance to specify the type of object to be created, and creates new objects by copying these prototypes. Create another customizable object from one object without knowing any creation details.
Prototype shallow copy - code display

<?php

abstract class Prototype
{
    
    
    private $id;
    public $v = PHP_EOL;
    function __construct($id)
    {
    
    
        $this->id = $id;
        echo 'create' . PHP_EOL;
    }
    public function getID()
    {
    
    
        return $this->id;
    }
    public abstract function cloneObj();
}

class ConcretePrototype extends Prototype
{
    
    

    public function run()
    {
    
    
        echo '复制来,复制去,都是自己';
    }

    public function cloneObj()
    {
    
    
        return clone $this;
    }
}

class Client
{
    
    
   public function execute()
   {
    
    
       $prototype = new ConcretePrototype('ME');
       $clone = $prototype->cloneObj();
       echo 'ID是' . $clone->getID() . "\n";
       $clone->run();
       echo $prototype->v . '我是原型';
       echo $clone->v . '我是克隆';
   }
}
$client = new Client();
$client->execute();

Prototype deep copy - code demo

<?php

interface ICloneable
{
    
    
    public function cloneObj();
    public function setPersonalInfo($name, $age);
    public function setWorkExperience($company);
    public function display();
}

class Person implements ICloneable
{
    
    

    private $name;
    private $sex;
    private $work;
    function __construct($work)
    {
    
    
        $this->work = $work;
    }

    public function run()
    {
    
    
        echo '复制来,复制去,都是自己';
    }

    public function cloneObj()
    {
    
    
        $person = new Person($this->work);
        $person->sex = $this->sex;
        $person->name = $this->name;
        return $person;
    }

    public function setPersonalInfo($name, $sex)
    {
    
    
        $this->name = $name;
        $this->sex = $sex;
    }

    public function setWorkExperience($company)
    {
    
    
        $this->work->company = $company;
    }

    public function display()
    {
    
    
        echo $this->name . "\n";
        echo $this->sex . "\n";
        echo $this->work->workDate . '进入' . $this->work->company . "\n";

    }
}

class WorkExperience
{
    
    
    public $company;
    public $workDate;

}

class Client
{
    
    
    public function execute()
    {
    
    
        $prototype = new Person(new WorkExperience());
        $prototype->setPersonalInfo('ztf' , '男');
        $prototype->setWorkExperience('百度');
        $clone = $prototype->cloneObj();
        $prototype->display();
        $clone->display();
    }
}
$client = new Client();
$client->execute();

Structural

6. Adapter mode

UML
insert image description here
parses
the adapter pattern, which converts the interface of a class into another interface that customers want. The Adapter pattern enables classes that would otherwise not work together due to incompatible interfaces to work together.
Adaptation situation: When the data and behavior of the system are correct, but the interface does not match, we should consider using an adapter when both parties are not easy to modify.

<?php

/**
 * Class Player
 * Target 客户所期待的接口,可以是具体的或抽象的类,也可以是接口
 */
abstract class Player
{
    
    
    public $name;
    function __construct($name)
    {
    
    
        $this->name = $name;
    }
    public abstract function attack();
    public abstract function defense();
}

/**
 * Class Forwards
 */
class Forwards extends Player     //前锋
{
    
    
    function __construct($name)
    {
    
    
        parent::__construct($name);
    }

    public function attack()
    {
    
    
        echo $this->name . '进攻' . "\n";
    }

    public function defense()
    {
    
    
        echo $this->name . '防守' . "\n";
    }
}

class ForeignCenter                       //Adaptee需要适配的类
{
    
    
    private $name;

    public function setName($name)
    {
    
    
        $this->name = $name;
    }

    public function getName()
    {
    
    
        return $this->name;
    }

    public function attack()
    {
    
    
        echo '外籍中锋' . $this->name . '进攻' . "\n";
    }

    public function defense()
    {
    
    
        echo '外籍中锋' . $this->name . '防守' . "\n";
    }

}

/**
 * Class Translator
 * Adapter通过在内部包装一个 Adaptee 对象,把源接口转换成目标接口
 */
class Translator extends Player                      //翻译者
{
    
    

    private $foreignCenter;

    function __construct($name)
    {
    
    
        parent::__construct($name);
        $this->foreignCenter = new ForeignCenter();
        $this->foreignCenter->setName($name);
    }

    public function attack()
    {
    
    
        $this->foreignCenter->attack();
    }

    public function defense()
    {
    
    
        $this->foreignCenter->defense();
    }
}

class Client
{
    
    
    public function Main()
    {
    
    
        $player = new Forwards('詹姆斯');
        $player->attack();
        $FP = new Translator('姚明');
        $FP->attack();
        $FP->defense();
    }
}
$client = new Client();
$client->Main();

7. Decoration mode

UML
insert image description here
parses
the decoration pattern, which dynamically adds some additional responsibilities to an object. In terms of adding functionality, the decoration pattern is more flexible than generating subclasses.
Adaptation situation: Generally, new fields, new methods and new logic are added to the class, thereby increasing the complexity of the main class, and these newly added things are only to meet some requirements that will only be executed under certain circumstances The need for special behavior. The decorator puts each function to be decorated in a separate class, and makes this class wrap the object it wants to decorate.
code display

<?php

abstract class Component
{
    
    
    public abstract function operation();
}

class ConcreteComponent extends Component
{
    
    

    public function operation()
    {
    
    
       echo '具体对象的操作' . "\n";
    }
}

abstract class Decorator extends Component
{
    
    
    protected $component;

    public function setComponent($component)
    {
    
    
        $this->component = $component;
    }

    public function operation()
    {
    
    
        if ($this->component != null) {
    
    
            $this->component->operation();
        }
    }

}

class ConcreteDecoratorA extends Decorator
{
    
    
    public function operation()
    {
    
    
        //首先运行原Component的operation(),再执行本类的功能,如AddedBehavior(),相当于对原Component进行装饰
        parent::operation();
        $addedState = 'New State';
        echo '具体装饰对象A的操作' . "\n";
    }
}

class ConcreteDecoratorB extends Decorator
{
    
    
    public function operation()
    {
    
    
        parent::operation();
        $this->AddedBehavior();
        echo '具体装饰对象B的操作' . "\n";
    }

    private function AddedBehavior()
    {
    
    
        echo '新行为' . "\n";
    }
}

$c = new ConcreteComponent();
$Ad = new ConcreteDecoratorA();
$Bd = new ConcreteDecoratorB();

$Ad->setComponent($c);
$Bd->setComponent($Ad);
$Bd->operation();

8. Bridge mode

UML
insert image description here
Parsing
The Bridge pattern, which separates the abstraction from its implementation so that they can both vary independently. Implementation refers to the objects that an abstract class and its derived classes use to implement themselves.
Usage: When the system has the possibility of multi-angle classification, and each classification may change, then separate this multi-angle, let them change independently, and reduce the coupling between them.
code display

<?php

abstract class Implementor
{
    
    
    public abstract function operation();
}

class ConcreteImplementorA extends Implementor                 //模块二
{
    
    

    public function operation()
    {
    
    
        echo '具体实现 A 的方法执行' . "\n";
    }
}

class ConcreteImplementorB extends Implementor
{
    
    

    public function operation()
    {
    
    
        echo '具体实现 B 的方法执行' . "\n";
    }
}

class Abstraction                                             //抽象关联类
{
    
    
    protected $implementor;

    public function setImplementor($implementor)              //桥接,关联方法
    {
    
    
        $this->implementor = $implementor;
    }

    public function operation()
    {
    
    
        $this->implementor->operation();
    }
}

class RefinedAbstraction extends Abstraction                  //模块一
{
    
    
    public function operation()
    {
    
    
        $this->implementor->operation();
    }
}

$ab = new RefinedAbstraction();
$ab->setImplementor(new ConcreteImplementorA());
$ab->operation();
$ab->setImplementor(new ConcreteImplementorB());
$ab->operation();

9. Combination mode

UML
insert image description here
analysis
Composite mode, which combines objects into a tree structure to represent the 'part-whole' hierarchy. Basic objects can be composed into more complex composite objects, which in turn can be composed, and so on, recursively. Composite mode enables users to use single objects and composite objects with consistency.
Applicable situation: When the requirement is a partial and overall hierarchical structure, and you want users to ignore the difference between the combined object and a single object, and use all the objects in the combined structure uniformly.
code display

<?php

abstract class Component
{
    
    
    public $name;

    function __construct($name)
    {
    
    
        $this->name = $name;
    }

    public abstract function add($component);
    public abstract function remove($component);
    public abstract function display($depth);
}

class Leaf extends Component
{
    
    
    //因为叶子没有再增加分枝和树叶,add 和 remove 没有意义,
    //但是为了消除叶节点和枝节点对象在抽象层的区别,它们具有一致的接口
    public function add($component)
    {
    
    
        echo '我不是枝干' . "\n";
    }

    public function remove($component)
    {
    
    
        echo '不能从一个叶子节点移除节点' . "\n";
    }

    public function display($depth)
    {
    
    
        echo str_repeat('-', $depth) . $this->name . "\n";
    }
}

class Composite extends Component
{
    
    
    private $listComponent = array();

    public function add($component)
    {
    
    
        $this->listComponent[$component->name] = $component;
    }

    public function remove($component)
    {
    
    
        unset($this->listComponent[$component->name]);
    }

    public function display($depth)
    {
    
    
        foreach ($this->listComponent as $key => $value) {
    
    
            $value->display($depth + 2);
        }
    }
}

$root = new Composite('root');
$root->add(new Leaf('Leaf A'));
$root->add(new Leaf('Leaf B'));
$comp = new Composite('Composite X');
$comp->add(new Leaf('Leaf XA'));
$root->add($comp);
$leaf = new Leaf('Leaf D');
$root->add($leaf);
$root->remove($leaf);
$root->display(1);

10. Flyweight mode

UML
insert image description here
parsing
The sharing pattern uses sharing technology to effectively support a large number of fine-grained objects and avoid the overhead of a large number of very similar classes. In programming, sometimes it is necessary to generate a large number of fine-grained class instances to represent data. Finding that these instances are essentially the same except for a few parameters can sometimes drastically reduce the number of classes that need to be instantiated.
Adapt to the situation:

  1. When an application uses a large number of objects, and a large number of these objects cause a large storage overhead, it should consider using
  2. Most of the state of the object can be external state, if the external state of the object is removed, then many composite objects can be replaced by relatively few shared objects.
    code display
<?php

abstract class Flyweight
{
    
    
    public abstract function operation($extrinsicState);
}

class ConcreteFlyweight extends Flyweight
{
    
    

    public function operation($extrinsicState)
    {
    
    
        echo '具体的 Flyweight';
        var_dump($extrinsicState);
    }
}

class UnsharedConcreteFlyweight extends Flyweight
{
    
    

    public function operation($extrinsicState)
    {
    
    
        echo '不共享具体的 Flyweight';
        var_dump($extrinsicState);
    }
}

class FlyweightFactory
{
    
    
    private $flyweights = array();

    function __construct()
    {
    
    
        $this->flyweights['X'] = new ConcreteFlyweight();
        $this->flyweights['Y'] = new ConcreteFlyweight();
        $this->flyweights['Z'] = new ConcreteFlyweight();
    }

    public function getFlyweight($key)
    {
    
    
        return $this->flyweights[$key];
    }
}

class Client
{
    
    
    public function execute()
    {
    
    
        $extrinsicState = 22;         //代码外部状态
        $f = new FlyweightFactory();
        $fx = $f->getFlyweight('X');
        $fx->operation(--$extrinsicState);

        $fy = $f->getFlyweight('Y');
        $fy->operation(--$extrinsicState);

        $fz = $f->getFlyweight('Z');
        $fz->operation(--$extrinsicState);

        $uf = new UnsharedConcreteFlyweight();
        $uf->operation(--$extrinsicState);
    }
}
$client = new Client();
$client->execute();

11. Proxy mode

UML
insert image description here
parses
the proxy pattern, which provides a proxy for other objects to control access to this object.
Applicable situation:

  1. A remote proxy is to provide a local representation of an object in a different address space. This hides the fact that an object exists in a different address space.
  2. Virtual proxies that create expensive objects on demand. Use it to store real objects that take a long time to instantiate.
  3. Security proxy, used to control the permissions of real object access. Generally used for objects that should have different access rights.
  4. Smart guide, when calling the real object, the proxy handles something else.
    code display
<?php

abstract class Subject
{
    
    
    public abstract function Request();
}

class RealSubject extends Subject
{
    
    

    public function Request()
    {
    
    
        echo '真实的请求';
    }
}

class Proxy extends Subject
{
    
    
    private $realSubject;
    public function Request()
    {
    
    
        if ($this->realSubject == null) {
    
    
            $this->realSubject = new RealSubject();
        }
        $this->realSubject->Request();
    }
}

class Client
{
    
    
    public function execute()
    {
    
    
        $proxy = new Proxy();
        $proxy->Request();
    }
}
$client = new Client();
$client->execute();

12. Appearance mode

UML
insert image description here
analysis
Appearance mode, which provides a consistent interface for a set of interfaces in the subsystem, this mode defines a high-level interface, this interface makes this subsystem easier to use.
Applicable situation:

  1. At the beginning of the design, the two different layers should be consciously separated
  2. In the development stage, subsystems often become more and more complex due to continuous refactoring and evolution. Adding Facade can provide a simple interface and reduce the dependencies between them.
  3. When maintaining a legacy large-scale system, it may be very difficult to maintain and expand the system, but it contains very important functions, and the development of new requirements must rely on it Code
    display
<?php

class SubSystemOne
{
    
    
    public function MethodOne()
    {
    
    
        echo '子系统方法一' . "\n";
    }
}

class SubSystemTwo
{
    
    
    public function MethodTwo()
    {
    
    
        echo '子系统方法二' . "\n";
    }
}

class SubSystemThree
{
    
    
    public function MethodThree()
    {
    
    
        echo '子系统方法三' . "\n";
    }
}

class Facade
{
    
    
    private $subSystemOne;
    private $subSystemTwo;
    private $subSystemThree;

    function __construct()
    {
    
    
        $this->subSystemOne = new SubSystemOne();
        $this->subSystemTwo = new SubSystemTwo();
        $this->subSystemThree = new SubSystemThree();
    }

    public function methodA()
    {
    
    
        echo '方法组A() ------' . "\n";
        $this->subSystemOne->MethodOne();
        $this->subSystemThree->MethodThree();
    }

    public function MethodB()
    {
    
    
        echo '方法组B() ------' . "\n";
        $this->subSystemTwo->MethodTwo();
        $this->subSystemThree->MethodThree();
    }
}

class Client
{
    
    
    public function execute()
    {
    
    
        $facade = new Facade();
        $facade->MethodA();
        $facade->MethodB();
    }
}
$client = new Client();
$client->execute();

Behavioral

13. Command mode

Guess you like

Origin blog.csdn.net/weixin_43885417/article/details/107024699