ホームページ >バックエンド開発 >PHPチュートリアル >PHP実践デザインパターン [翻訳]

PHP実践デザインパターン [翻訳]

WBOY
WBOYオリジナル
2016-06-23 13:25:37898ブラウズ

??> 元のアドレス:

PHP のデザイン パターン

この記事では主に、Web 開発、正確には PHP 開発における関連するデザイン パターンとその応用について説明します。経験豊富な開発者は確かにデザイン パターンに精通していますが、この記事は主に若手開発者を対象としています。まず、デザイン パターンとは何かを理解する必要があります。デザイン パターンは、リンク リストのような一般的なデータ構造でも、特別なアプリケーションやフレームワークのデザインでもありません。実際、デザイン パターンは次のように説明されます:

特定のコンテキストで一般的なデザインの問題を解決するためにカスタマイズされたオブジェクトとクラスの通信の説明

一方、デザイン パターンは、広く再利用可能な解決方法を提供します。日々のプログラミングでよく遭遇する問題。デザイン パターンは必ずしもクラス ライブラリやサードパーティのフレームワークである必要はなく、アイデアのようなものであり、システムで広く使用されています。これらは、さまざまなシナリオで問題を解決するために使用できるパターンまたはテンプレートとしても表示されます。デザイン パターンを使用すると、開発をスピードアップし、多くの大きなアイデアやデザインを簡単な方法で実装できます。もちろん、デザイン パターンは開発において非常に役立ちますが、不適切なシナリオでの誤用は避けなければなりません。

現在 23 の一般的な設計パターンがあり、さまざまな使用目標に応じて次の 3 つのカテゴリに分類できます:

  • 作成パターン: オブジェクトを実装から分離するためにオブジェクトを作成するために使用されます。

  • アーキテクチャパターン: 異なるオブジェクト間に大きなオブジェクト構造を構築するために使用されます。

  • 行動パターン: 異なるオブジェクト間のアルゴリズム、関係、責任を管理するために使用されます。

作成パターン

シングルトン (シングルトン モード)

シングルトン モードは、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);// exampleprint_r($secondProduct->mix);// example

多くの場合、システム内の複数のクラスに対してシングルトン構築メソッドを作成する必要があります。この方法で、一般的な抽象親ファクトリー メソッドを確立できます。

<?phpabstract 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)

レジストリ

登録デスク パターンはあまりありません。これは一般的な作成モードではなく、静的メソッドを使用してより簡単にデータにアクセスするためのものです。

<?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 (ファクトリー パターン)

ファクトリ パターンは、その名前が示すように、非常によく使用されるもう 1 つのパターンです。これは確かにオブジェクト インスタンスの生産ファクトリーです。ある意味、ファクトリ パターンは、オブジェクトの特定の内部実装を気にせずにオブジェクトを取得するのに役立つ一般的なメソッドを提供します。

<?phpinterface 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 productprint_r($secondProduct->getName());// Second product

AbstractFactory (抽象ファクトリ パターン)

場合によっては、異なる選択ロジックに基づいて異なる構築ファクトリを提供する必要があり、複数のファクトリには統合された抽象ファクトリが必要です:

<?phpclass 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 factoryprint_r($secondProduct->getName());// Second product from second factory

オブジェクト プール (オブジェクト プール)

Objectプールは、一連のオブジェクトを構築して保存し、必要に応じて呼び出しを取得するために使用できます:

<?phpclass 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());// firstprint_r(Factory::getProduct('second')->getId());// second

Lazy Initialization (遅延初期化)

特定の変数の遅延初期化もよく使用されます。クラス言語ではよく使用されません。どの関数が使用されるかがわかっており、一部の関数は多くの場合 1 回だけ必要になります。

<?phpinterface 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 productprint_r($factory->getSecondProduct()->getName());// Second productprint_r($factory->getFirstProduct()->getName());// The first product

Prototype (プロトタイプ モード)

場合によっては、一部のオブジェクトを複数回初期化する必要があることがあります。特に初期化に多くの時間とリソースが必要な場合は、これらのオブジェクトを事前に初期化して保存してください。

<?phpinterface 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 productprint_r($secondProduct->name);// Second product

Builder(Constructor)

Constructor パターンは、主にいくつかの複雑なオブジェクトの作成に関するものです:

<?phpclass 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 builderprint_r($secondDirector->getProduct()->getName());// The product of second builder
構造パターン

Decorator(Decorator パターン)

Decorator パターンを使用すると、実行時にさまざまなシナリオに基づいて特定のオブジェクトを動的に作成できます。オブジェクトが呼び出される前後の動作。

<?phpclass 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]);    }}

Adapter (アダプター モード)

このモードでは、さまざまなインターフェイスを使用して特定のクラスを再構築することができ、さまざまな呼び出しメソッドの使用が可能になります:

<?phpclass 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/>";}
動作パターン

Strategy (Strategy (戦略モード)

テスト モードは主に、クライアント クラスが特定の実装を知らなくても特定のアルゴリズムをより適切に使用できるようにするためです。

<?phpinterface 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;    }}

Observer (Observer パターン)

他のオブジェクトが何らかの方法でオブザーバーとして登録できるようにすることで、オブジェクトを監視可能に設定できます。観察されるオブジェクトが変化するたびに、メッセージが観察者に送信されます。

<?phpinterface 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" );

責任の連鎖(責任連鎖モデル)

このモデルは別名、制御連鎖モデルとも呼ばれます。これは主に、特定のコマンドに対する一連のプロセッサで構成され、各クエリはプロセッサによって形成された一連の責任の中で渡され、プロセッサは応答して処理する必要があるかどうかを判断します。プロセッサがリクエストを処理できる間、各ハンドラは一時停止されます。

リーリー

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。