PHP设计模式

1 篇文章 0 订阅

完成度50%

原文地址:https://www.devbattles.com/en/sand/post-1306-Design+Patterns+in+PHP#.Vg9o9Ohl9Bk.twitter


Patterns in php. Today we are going to talk about design patterns in web development, more precisely – in PHP. Experienced developers are probably familiar with this, but this article will be extremely useful for all novice developers. So, what is it – design patterns? Design Patterns aren’t analysis patterns, they are not descriptions of common structures like linked lists, nor are they particular application or framework designs. In fact, design patterns are “descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.” In other words, Design patterns provide a generic reusable solution to the programming problems that we encounter every day. Design patterns are not ready classes or libraries, that can be simply applied to your system, this is not a concrete solution that can be converted in to source code, design patterns are much more than that. They are patterns, or templates, that can be implemented to solve a problem in different particular situations.

PHP中的设计模式。今天我们将在PHP中讨论Web开发中的设计模式。经验丰富的开发人员可能熟悉这一点,但这篇文章将对所有新手开发人员非常有用。那什么是设计模式?设计模式不是分析模式,它们不是链接列表等常见结构的描述,也不是特定的应用程序或框架设计。实际上,设计模式是“定制的通信对象和类的描述,以解决特定环境中的一般设计问题”。换句话说,设计模式为我们每天遇到的编程问题提供通用的可重用的解决方案。设计模式尚未准备好类或库,可以简单地应用于您的系统,这不是可以转换为源代码的具体解决方案,设计模式远不止于此。它们是可以实现以在不同特定情况下解决问题的模式或模板。

Design patterns help to speed up the development, as the templates are proven and from the developer’s position, only implementation is required. Design patterns not only make software development faster, but also encapsulate big ideas in a simpler way. Also, be careful not to use them in wrong places in order to avoid unpleasant situations. In addition to the theory, we also give you the most abstract and simple examples of design patterns.

设计模式有助于加快开发速度,因为模板已经被证明,并且从开发者的角度来看,只需要实现。设计模式不仅使软件开发更快,而且还以更简单的方式封装了大的想法。另外,为避免不愉快的情况,请小心不要在错误的地方使用它们。除了理论,我们还给你最抽象和简单的设计模式的例子。

“Each pattern describes a problem which occurs over and over again … and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without doing it the same way twice.” – Christopher Alexander

“每个模式描述了一个又一个发生的问题,然后描述了该问题的解决方案的核心,这样可以使用这个解决方案百万次,而不用两次相同的方式。” - 克里斯托弗·亚历山大

By now there are 23 different known design patterns, and they can be separated into three categories by purpose:
Creational Patterns: used to construct objects such that they can be decoupled from their implementing system
Structural Patterns: used to form large object structures between many disparate objects
Behavioral Patterns: used to manage algorithms, relationships, and responsibilities between objects
现在有23种不同的已知设计模式,它们可以分为三类:
创建模式:用于构建对象,使其可以与其实现系统脱钩
结构模式:用于在许多不同对象之间形成大型对象结构
行为模式:用于管理对象之间的算法,关系和责任

Complete list of design patterns you can find below:

PurposeDesign PatternAspect(s) that can vary
CreationalAbstract Factoryfamilies of product objects
Builderhow a composite object gets created
Factory Methodsubclass of object that is instantiated
Prototypeclass of object that is instantiated
Singletonthe sole instance of a class

您可以在下面找到完整的设计模式列表:

目的设计模式方面可以变化
创建 抽象工厂 家庭的产品对象
生成器如何创建复合对象
工厂方法被实例化的对象的子类
原型实例化的对象类
单例模式 课程的唯一实例
StructuralAdapterinterface to an object
Bridgeimplementation of an object
Compositestructure and composition of an object
Decoratorresponsibilities of an object without subclassing
Facadeinterface to a subsystem
Flyweightstorage costs of objects
Proxyhow an object is accessed; its location
结构适配器对象的接口
桥接一个对象的实现
组合物体的结构和组成
装饰没有子类化的对象的责任
门面接口到子系统
享元对象的存储成本
代理如何访问对象; 它的位置


BehavioralChain of Responsibilityobject that can fulfill a request
Commandwhen and how a request is fulfilled
Interpretergrammar and interpretation of a language
Iteratorhow an aggregate’s elements are accessed, traversed
Mediatorhow and which objects interact with each other
Mementowhat private information is stored outside an object, and when
Observernumber of objects that depend on another object; how the dependent objects stay up to date
Statestates of an object
Strategyan algorithm
Template Methodsteps of an algorithm
Visitoroperations that can be applied to object(s) without changing their class(es)
行为的责任链可以满足请求的对象
命令何时以及如何满足请求
解释器语法和语言的解释
迭代器聚合元素如何被访问,遍历
中介者如何和哪些对象相互交互
备忘录什么私人信息存储在对象之外,何时
观察者取决于另一个对象的对象数; 依赖对象如何保持最新
状态一个对象的状态
战略一个算法
模板方法算法的步骤
访问者可以应用于对象而不改变其类的操作

And now, we can start overview some of the listed patterns

现在,我们可以开始概述一些列出的模式

Singleton

This is one of the most popular patterns. When developing web applications, it often makes sense conceptually and architecturally to allow access to only one instance of a particular class (during runtime). The singleton pattern enables us to do this. Example:

单例

这是最受欢迎的模式之一。在开发Web应用程序时,通常在概念上和架构上有意义地允许访问特定类的一个实例(在运行时期间)。单身形式使我们能够做到这一点。例:

<?php
/**
 * Singleton class
 */
final class Product
{

    /**
     * @var self
     */
    private static $instance;

    /**
     * @var mixed
     */
    public $mix;


    /**
     * Return self instance
     *
     * @return self
     */
    public static function getInstance() {
        if (!(self::$instance instanceof self)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
    }

    private function __clone() {
    }
}

$firstProduct = Product::getInstance();
$secondProduct = Product::getInstance();

$firstProduct->mix = 'test';
$secondProduct->mix = 'example';

print_r($firstProduct->mix);
// example
print_r($secondProduct->mix);
// example


Multiton

Maybe someone will want to use a variety of singletons in your project:

多例

也许有人会想在你的项目中使用各种单身人士:

<?php

abstract class FactoryAbstract {

    protected static $instances = array();

    public static function getInstance() {
        $className = static::getClassName();
        if (!(self::$instances[$className] instanceof $className)) {
            self::$instances[$className] = new $className();
        }
        return self::$instances[$className];
    }

    public static function removeInstance() {
        $className = static::getClassName();
        if (array_key_exists($className, self::$instances)) {
            unset(self::$instances[$className]);
        }
    }

    final protected static function getClassName() {
        return get_called_class();
    }

    protected function __construct() { }

    final protected function __clone() { }
}

abstract class Factory extends FactoryAbstract {

    final public static function getInstance() {
        return parent::getInstance();
    }

    final public static function removeInstance() {
        parent::removeInstance();
    }
}
// using:

class FirstProduct extends Factory {
    public $a = [];
}
class SecondProduct extends FirstProduct {
}

FirstProduct::getInstance()->a[] = 1;
SecondProduct::getInstance()->a[] = 2;
FirstProduct::getInstance()->a[] = 3;
SecondProduct::getInstance()->a[] = 4;

print_r(FirstProduct::getInstance()->a);
// array(1, 3)
print_r(SecondProduct::getInstance()->a);
// array(2, 4)

Strategy

The strategy pattern is based on algorithms. You encapsulate specific families of algorithms allowing the client class responsible for instantiating a particular algorithm to have no knowledge of the actual implementation. Example:

战略

策略模式是基于算法的。您封装了特定的算法系列,允许客户机级别负责实例化特定算法,而不了解实际的实现。例:
 

<?php

interface OutputInterface {
    public function load();
}

class SerializedArrayOutput implements OutputInterface {
    public function load() {
        return serialize($arrayOfData);
    }
}

class JsonStringOutput implements OutputInterface {
    public function load() {
        return json_encode($arrayOfData);
    }
}

class ArrayOutput implements OutputInterface {
    public function load() {
        return $arrayOfData;
    }
}

Decorator

This pattern allows us to add new or additional behavior to an object during runtime, depending on the situation. Example:

装饰

这种模式允许我们根据情况在运行时向对象添加新的或附加的行为。例:
 

<?php
class HtmlTemplate {
    // any parent class methods
}
 
class Template1 extends HtmlTemplate {
    protected $_html;
     
    public function __construct() {
        $this->_html = "<p>__text__</p>";
    }
     
    public function set($html) {
        $this->_html = $html;
    }
     
    public function render() {
        echo $this->_html;
    }
}
 
class Template2 extends HtmlTemplate {
    protected $_element;
     
    public function __construct($s) {
        $this->_element = $s;
        $this->set("<h2>" . $this->_html . "</h2>");
    }
     
    public function __call($name, $args) {
        $this->_element->$name($args[0]);
    }
}
 
class Template3 extends HtmlTemplate {
    protected $_element;
     
    public function __construct($s) {
        $this->_element = $s;
        $this->set("<u>" . $this->_html . "</u>");
    }
     
    public function __call($name, $args) {
        $this->_element->$name($args[0]);
    }
}

Registry

This pattern is a bit unusual from the overall list, because it is not a Creational pattern. Well, register – it is hash, and you access to data through the static methods:

 

<?php
/**
* Registry class
*/
class Package {

    protected static $data = array();

    public static function set($key, $value) {
        self::$data[$key] = $value;
    }

    public static function get($key) {
        return isset(self::$data[$key]) ? self::$data[$key] : null;
    }

    final public static function removeObject($key) {
        if (array_key_exists($key, self::$data)) {
            unset(self::$data[$key]);
        }
    }
}


Package::set('name', 'Package name');

print_r(Package::get('name'));
// Package name

Factory

This is another very known pattern. It acts exactly as it sounds: this is class that does as the real factory of object instances. In other words, assume that we know that there are factories that produce some kind of a product. We do not care how a factory makes this product, but we know that any factory has one universal way to ask for it:
 

 

<?php

interface Factory {
    public function getProduct();
}

interface Product {
    public function getName();
}

class FirstFactory implements Factory {

    public function getProduct() {
        return new FirstProduct();
    }
}

class SecondFactory implements Factory {

    public function getProduct() {
        return new SecondProduct();
    }
}

class FirstProduct implements Product {

    public function getName() {
        return 'The first product';
    }
}

class SecondProduct implements Product {

    public function getName() {
        return 'Second product';
    }
}

$factory = new FirstFactory();
$firstProduct = $factory->getProduct();
$factory = new SecondFactory();
$secondProduct = $factory->getProduct();

print_r($firstProduct->getName());
// The first product
print_r($secondProduct->getName());
// Second product

Abstract Factory

There are situations when we have some of the same type of factories and we want to encapsulate the logic of choice, what of the factories use to a given task. This pattern cames to the rescue:
 

 

<?php

class Config {
    public static $factory = 1;
}

interface Product {
    public function getName();
}

abstract class AbstractFactory {

    public static function getFactory() {
        switch (Config::$factory) {
            case 1:
                return new FirstFactory();
            case 2:
                return new SecondFactory();
        }
        throw new Exception('Bad config');
    }

    abstract public function getProduct();
}

class FirstFactory extends AbstractFactory {
    public function getProduct() {
        return new FirstProduct();
    }
}
class FirstProduct implements Product {
    public function getName() {
        return 'The product from the first factory';
    }
}

class SecondFactory extends AbstractFactory {
    public function getProduct() {
        return new SecondProduct();
    }
}
class SecondProduct implements Product {
    public function getName() {
        return 'The product from second factory';
    }
}

$firstProduct = AbstractFactory::getFactory()->getProduct();
Config::$factory = 2;
$secondProduct = AbstractFactory::getFactory()->getProduct();

print_r($firstProduct->getName());
// The first product from the first factory
print_r($secondProduct->getName());
// Second product from second factory

Observer

An object is made observable by adding a method that allows another object, the observer to get registered. If the observable object gets changed, it sends a message to the objects which are registered as observers:
 

 

<?php

interface Observer {
  function onChanged($sender, $args);
}

interface Observable {
  function addObserver($observer);
}

class CustomerList implements Observable {
  private $_observers = array();

  public function addCustomer($name) {
    foreach($this->_observers as $obs)
      $obs->onChanged($this, $name);
  }

  public function addObserver($observer) {
    $this->_observers []= $observer;
  }
}

class CustomerListLogger implements Observer {
  public function onChanged($sender, $args) {
    echo( "'$args' Customer has been added to the list \n" );
  }
}

$ul = new UserList();
$ul->addObserver( new CustomerListLogger() );
$ul->addCustomer( "Jack" );

Adapter

This pattern allows you to repurpose a class with a different interface, allowing it to be used by a system which uses different calling methods:
 

 

<?php

class SimpleBook {

    private $author;
    private $title;

    function __construct($author_in, $title_in) {
        $this->author = $author_in;
        $this->title  = $title_in;
    }

    function getAuthor() {
        return $this->author;
    }

    function getTitle() {
        return $this->title;
    }
}

class BookAdapter {

    private $book;

    function __construct(SimpleBook $book_in) {
        $this->book = $book_in;
    }
    function getAuthorAndTitle() {
        return $this->book->getTitle().' by '.$this->book->getAuthor();
    }
}

// Usage
$book = new SimpleBook("Gamma, Helm, Johnson, and Vlissides", "Design Patterns");
$bookAdapter = new BookAdapter($book);
echo 'Author and Title: '.$bookAdapter->getAuthorAndTitle();

function echo $line_in) {
  echo $line_in."<br/>";
}

Lazy Initialization

Here is another interesting situation. Imagine that you have a factory, but you do not know what part of its functionality you need, and what – no. In such cases, the necessary operations are performed only if they are needed and only once:
 

 

<?php

interface Product {
    public function getName();
}

class Factory {

    protected $firstProduct;
    protected $secondProduct;

    public function getFirstProduct() {
        if (!$this->firstProduct) {
            $this->firstProduct = new FirstProduct();
        }
        return $this->firstProduct;
    }

    public function getSecondProduct() {
        if (!$this->secondProduct) {
            $this->secondProduct = new SecondProduct();
        }
        return $this->secondProduct;
    }
}

class FirstProduct implements Product {
    public function getName() {
        return 'The first product';
    }
}

class SecondProduct implements Product {
    public function getName() {
        return 'Second product';
    }
}


$factory = new Factory();

print_r($factory->getFirstProduct()->getName());
// The first product
print_r($factory->getSecondProduct()->getName());
// Second product
print_r($factory->getFirstProduct()->getName());
// The first product

Chain of responsibility

The pattern also has another name – Chain of Command. It follows a chain of command with a series of handlers. The message (query) runs through a series of these handlers and at each junction it is regulated whether the handler can handle the query or not. The process stops the moment a handler can handle the request:
 

 

<?php

interface Command {
    function onCommand($name, $args);
}

class CommandChain {
    private $_commands = array();

    public function addCommand($cmd) {
        $this->_commands[]= $cmd;
    }

    public function runCommand($name, $args) {
        foreach($this->_commands as $cmd) {
            if ($cmd->onCommand($name, $args))
                return;
        }
    }
}

class CustCommand implements Command {
    public function onCommand($name, $args) {
        if ($name != 'addCustomer')
            return false;
        echo("This is CustomerCommand handling 'addCustomer'\n");
        return true;
    }
}

class MailCommand implements Command {
    public function onCommand($name, $args) {
        if ($name != 'mail')
            return false;
        echo("This is MailCommand handling 'mail'\n");
        return true;
    }
}

$cc = new CommandChain();
$cc->addCommand( new CustCommand());
$cc->addCommand( new MailCommand());
$cc->runCommand('addCustomer', null);
$cc->runCommand('mail', null);

Object pool

Object pool – is a hash, which can be stacked to initialize an object and get them out if needed:

 

<?php

class Product {

    protected $id;

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

    public function getId() {
        return $this->id;
    }
}

class Factory {

    protected static $products = array();

    public static function pushProduct(Product $product) {
        self::$products[$product->getId()] = $product;
    }

    public static function getProduct($id) {
        return isset(self::$products[$id]) ? self::$products[$id] : null;
    }

    public static function removeProduct($id) {
        if (array_key_exists($id, self::$products)) {
            unset(self::$products[$id]);
        }
    }
}


Factory::pushProduct(new Product('first'));
Factory::pushProduct(new Product('second'));

print_r(Factory::getProduct('first')->getId());
// first
print_r(Factory::getProduct('second')->getId());
// second

Prototype

Sometime, some objects should be initialized multiple times. It makes sense to save on their initialization, especially if initialization requires time and resources. Prototype – a pre-initialized and saved object. If necessary, it could be cloned:
 

 

<?php

interface Product {
}

class Factory {

    private $product;

    public function __construct(Product $product) {
        $this->product = $product;
    }

    public function getProduct() {
        return clone $this->product;
    }
}

class SomeProduct implements Product {
    public $name;
}


$prototypeFactory = new Factory(new SomeProduct());

$firstProduct = $prototypeFactory->getProduct();
$firstProduct->name = 'The first product';

$secondProduct = $prototypeFactory->getProduct();
$secondProduct->name = 'Second product';

print_r($firstProduct->name);
// The first product
print_r($secondProduct->name);
// Second product

Builder

This template is used when we want to encapsulate the creation of a complex object:
 

 

<?php

class Product {

    private $name;

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

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

abstract class Builder {

    protected $product;

    final public function getProduct() {
        return $this->product;
    }

    public function buildProduct() {
        $this->product = new Product();
    }
}

class FirstBuilder extends Builder {

    public function buildProduct() {
        parent::buildProduct();
        $this->product->setName('The product of the first builder');
    }
}

class SecondBuilder extends Builder {

    public function buildProduct() {
        parent::buildProduct();
        $this->product->setName('The product of second builder');
    }
}

class Factory {

    private $builder;

    public function __construct(Builder $builder) {
        $this->builder = $builder;
        $this->builder->buildProduct();
    }

    public function getProduct() {
        return $this->builder->getProduct();
    }
}

$firstDirector = new Factory(new FirstBuilder());
$secondDirector = new Factory(new SecondBuilder());

print_r($firstDirector->getProduct()->getName());
// The product of the first builder
print_r($secondDirector->getProduct()->getName());
// The product of second builder





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值