ホームページ  >  記事  >  バックエンド開発  >  PHP 実践デザインパターン: PHP のデザインパターン

PHP 実践デザインパターン: PHP のデザインパターン

WBOY
WBOYオリジナル
2016-07-23 08:54:42797ブラウズ

この記事は翻訳記事です

元のアドレス: Design Patterns in PHP
PHP を学習する予定がある場合は、プログラミング言語学習知識システムの著者の重要なポイントのリストを参照してください

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

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

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

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

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

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

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

創造的なパターン シングルトン (シングルケースモード) シングルトン パターンは、Web アプリケーションの開発において、実行時に特定のクラスのアクセス可能なインスタンスを作成できるようにするためによく使用されるパターンの 1 つです。

/**
  • * シングルトンクラス
  • */
  • final class Product
  • {
  • /**
  • * @var self
  • */
  • private static $instance;
  • /**
  • * @var混合
  • */
  • public $mix;
  • /**
  • * 自己インスタンスを返す
  • *
  • * @return self
  • */
  • public static function getInstance() {
  • if (!(self::$instance instanceof self)) {
  • self::$instance = new self() ;
  • }
  • return self::$instance;
  • }
  • プライベート関数 __construct() {
  • }
  • プライベート関数 __clone() {
  • }
  • }
  • $firstProduct = Product::getInstance();
  • $secondProduct = Product::getInstance();
  • $firstProduct->mix = 'test';
  • $secondProduct->mix = 'example';
  • print_r($firstProduct->mix);
  • // example
  • print_r($secondProduct->mix);
  • // example
  • コードをコピー
  • 多くの場合、共通の抽象化を確立できるように、システム内の複数のクラスに対してシングルトン構築メソッドを作成する必要があります。親ファクトリ メソッド:

  • 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]) ]);
  • }
  • }
  • 最終保護された静的関数 getClassName() {
  • return get_called_class();
  • }
  • 保護関数 __construct() { }
  • 最終保護関数 __clone() { }
  • }
  • 抽象クラスFactory extends FactoryAbstract {
  • final public static function getInstance() {
  • returnparent::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)
  • コードをコピー
  • レジストリ

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

    1. /**
    2. * レジストリ クラス
    3. */
    4. class Package {
    5. protected static $data = array();
    6. public static function set($key, $value) {
    7. self: :$data[$key] = $value;
    8. }
    9. public static function get($key) {
    10. return isset(self::$data[$key]) : null ;
    11. }
    12. 最終的なパブリック静的関数 RemoveObject($key) {
    13. if (array_key_exists($key, self::$data)) {
    14. unset(self::$data[$key]);
    15. }
    16. }
    17. }
    18. Package::set('name', 'パッケージ名');
    19. print_r(Package::get('name'));
    20. //パッケージ名
    コードをコピー
    Factory(ファクトリーモード) )

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

    1. interface Factory {
    2. public function getProduct();
    3. }
    4. interface Product {
    5. public function getName();
    6. }
    7. class FirstFactoryimplements Factory {
    8. public function getProduct( ) {
    9. return new FirstProduct();
    10. }
    11. }
    12. class SecondFactory 実装 Factory {
    13. public function getProduct() {
    14. return new SecondProduct();
    15. }
    16. }
    17. class FirstProductimplements Product {
    18. public function getName() {
    19. return '最初の製品';
    20. }
    21. }
    22. class SecondProductimplements Product {
    23. public function getName() {
    24. return '2 番目の製品';
    25. }
    26. }
    27. $factory = new FirstFactory( );
    28. $firstProduct = $factory->getProduct();
    29. $factory = new SecondFactory();
    30. $secondProduct = $factory->getProduct();
    31. print_r($firstProduct->getName()) ;
    32. // 最初の製品
    33. print_r($secondProduct->getName());
    34. // 2 番目の製品
    コードをコピー
    AbstractFactory (抽象ファクトリーパターン)

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

    }
    インターフェース Product {
      public function getName();
    1. }
    2. abstract class AbstractFactory {
    3. public static function getFactory() {
    4. switch (Config::$factory) {
    5. case 1:
    6. return new FirstFactory( );
    7. ケース 2:
    8. return new SecondFactory();
    9. }
    10. throw new Exception('Bad config');
    11. }
    12. abstract public function getProduct();
    13. }
    14. class FirstFactory extends AbstractFactory {
    15. public function getProduct () {
    16. return new FirstProduct();
    17. }
    18. }
    19. class FirstProductimplements Product {
    20. public function getName() {
    21. return '最初の工場からの製品';
    22. }
    23. }
    24. class SecondFactory extends AbstractFactory {
    25. public function getProduct() {
    26. return new SecondProduct();
    27. }
    28. }
    29. class SecondProductimplements Product {
    30. public function getName() {
    31. return '第 2 工場からの製品';
    32. }
    33. }
    34. $ firstProduct = AbstractFactory ::getFactory()->getProduct();
    35. Config::$factory = 2;
    36. $secondProduct = AbstractFactory::getFactory()->getProduct();
    37. print_r($firstProduct->getName() );
    38. // 最初の工場からの最初の製品
    39. print_r($secondProduct->getName());
    40. // 第二工場からの二番目の製品
    41. コードをコピー
    42. オブジェクトプール

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

      1. class Product {
      2. protected $id;
      3. public function __construct($id) {
      4. $this->id = $id;
      5. }
      6. public function getId() {
      7. return $this->id;
      8. }
      9. }
      10. class Factory {
      11. protected static $products = array() ;
      12. public static function PushProduct(Product $product) {
      13. self::$products[$product->getId()] = $product;
      14. }
      15. public static function getProduct($id) {
      16. return isset( self ::$products[$id]) ? self::$products[$id] : null;
      17. }
      18. public static function RemoveProduct($id) {
      19. if (array_key_exists($id, self::$products) ) {
      20. unset(self::$products[$id]);
      21. }
      22. }
      23. }
      24. Factory::pushProduct(new Product('first'));
      25. Factory::pushProduct(new Product('first') ' ));
      26. print_r(Factory::getProduct('first')->getId());
      27. // first
      28. print_r(Factory::getProduct('first')->getId());
      29. / /second
      コードをコピー
      Lazy Initialization (遅延初期化)

      特定の変数の遅延初期化もよく使用されます。クラスでは、どの関数が使用されるかが不明であることが多く、一部の関数は 1 回だけ必要になることがよくあります。

      1. interface Product {
      2. public function getName();
      3. }
      4. class Factory {
      5. protected $firstProduct;
      6. protected $secondProduct;
      7. public function getFirstProduct() {
      8. if ( !$this->firstProduct) {
      9. $this->firstProduct = new FirstProduct();
      10. }
      11. return $this->firstProduct;
      12. }
      13. public function getSecondProduct() {
      14. if (!$this- >secondProduct) {
      15. $this->secondProduct = new SecondProduct();
      16. }
      17. return $this->secondProduct;
      18. }
      19. }
      20. class FirstProductimplements Product {
      21. public function getName() {
      22. return '最初の製品';
      23. }
      24. }
      25. クラス SecondProduct は Product {
      26. public function getName() {
      27. return '2 番目の製品';
      28. }
      29. }
      30. $factory = new Factory();
      31. print_r($ Factory->getFirstProduct()->getName());
      32. // 最初の製品
      33. print_r($factory->getSecondProduct()->getName());
      34. // 2 番目の製品
      35. print_r($factory ->getFirstProduct()->getName());
      36. // 最初の製品
      コードをコピー
      Prototype (プロトタイプ モード)

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

      1. interface Product {
      2. }
      3. class Factory {
      4. private $product;
      5. public function __construct(Product $product) {
      6. $this->product = $product;
      7. }
      8. public function getProduct() {
      9. return clone $this->product;
      10. }
      11. }
      12. class SomeProduct は Product を実装します {
      13. public $name;
      14. }
      15. $prototypeFactory = new Factory(new SomeProduct() );
      16. $firstProduct = $prototypeFactory->getProduct();
      17. $firstProduct->name = '最初の製品';
      18. $secondProduct = $prototypeFactory->getProduct();
      19. $secondProduct-> name = '2 番目の製品';
      20. print_r($firstProduct->name);
      21. // 最初の製品
      22. print_r($nextProduct->name);
      23. // 2 番目の製品
      コードをコピー
      ビルダー(造造者)

      造者モード主にいくつかのオブジェクトを作成するオブジェクト:

      1. class Product {
      2. private $name;
      3. public function setName($name) {
      4. $this->name = $name;
      5. }
      6. public function getName() {
      7. return $this->name;
      8. }
      9. }
      10. 抽象クラス Builder {
      11. protected $product;
      12. Final public function getProduct() {
      13. return $ this->product;
      14. }
      15. public function buildProduct() {
      16. $this->product = new Product();
      17. }
      18. }
      19. class FirstBuilder extends Builder {
      20. public function buildProduct() {
      21. parent ::buildProduct();
      22. $this->product->setName('最初のビルダーの製品');
      23. }
      24. }
      25. class SecondBuilder extends Builder {
      26. public function buildProduct() {
      27. parent: :buildProduct();
      28. $this->product->setName('2 番目のビルダーの製品');
      29. }
      30. }
      31. class Factory {
      32. private $builder;
      33. public function __construct(Builder $builder ) {
      34. $this->builder = $builder;
      35. $this->builder->buildProduct();
      36. }
      37. public function getProduct() {
      38. return $this->builder->getProduct( );
      39. }
      40. }
      41. $firstDirector = new Factory(new FirstBuilder());
      42. $secondDirector = new Factory(new SecondBuilder());
      43. print_r($firstDirector->getProduct()->getName( ));
      44. // 最初のビルダーの産物
      45. print_r($secondDirector->getProduct()->getName());
      46. // 2 番目のビルダーの産物
      复制代码
      構造パターン Decorator(装饰器模式)

      プラグインモードでは、実行時のさまざまな状況に応じて、特定のオブジェクトに対して前後に異なる実行動作を追加することが許可されています。

      class Template1 extends HtmlTemplate {
      protected $_html;
        public function __construct() {
      1. $this->gt;_html = "

        __text__

        ";
      2. }
      3. public function set($html) {
      4. $this->gt;_html = $html;
      5. }
      6. public function render() {
      7. echo $this->gt;_html;
      8. }
      9. }
      10. class Template2 extends HtmlTemplate {
      11. protected $_element;
      12. public function __construct($s) {
      13. $this->_element = $s;
      14. $this->set("

        " . $this->_html . "

        ");
      15. }
      16. public function __call($name, $args) {
      17. $this->element->$name($args[0]);
      18. }
      19. }
      20. class Template3 extends HtmlTemplate {
      21. protected $_element;
      22. public function __construct($s) {
      23. $this->_element = $s;
      24. $this->set("" . $this->_html . "") ;
      25. }
      26. public function __call($name, $args) {
      27. $this->_element->$name($args[0]);
      28. }
      29. }
      30. 复制代码
      31. Adapter(适器モード)
      32. このモードでは、異なるインターフェイスを使用して特定の種類を構築することができ、異なるインターフェイスを使用して実行することができます:
      class SimpleBook {

      private $author;

      private $title;
      function __construct($author_in, $title_in) {
        $this->author = $author_in;
      1. $this->title = $title_in;
      2. }
      3. function getAuthor() {
      4. return $this-> author;
      5. }
      6. function getTitle() {
      7. return $this->title;
      8. }
      9. }
      10. class BookAdapter {
      11. private $book;
      12. function __construct(SimpleBook $book_in) {
      13. $this-> ;book = $book_in;
      14. }
      15. function getAuthorAndTitle() {
      16. return $this->book->getTitle().' by '.$this->book->getAuthor();
      17. }
      18. }
      19. // 使い方
      20. $book = new SimpleBook("Gamma、Helm、Johnson、Vlissides", "Design Patterns");
      21. $bookAdapter = new BookAdapter($book);
      22. echo '著者とタイトル: '.$bookAdapter->getAuthorAndTitle();
      23. function echo $line_in) {
      24. echo $line_in."
        ";
      25. }
      26. 复制代
      27. 行動パターン ストラテジー(ストラテジーモード)

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

        1. interface OutputInterface {
        2. public functionload();
        3. }
        4. class SerializedArrayOutputimplements OutputInterface {
        5. public function load() {
        6. return Serialize($arrayOfData);
        7. }
        8. }
        9. クラス JsonStringOutput は OutputInterface {
        10. パブリック関数load() {
        11. return json_encode($arrayOfData);
        12. }
        13. }
        14. クラス ArrayOutput 実装 OutputInterface {
        15. パブリック関数load() {
        16. return $arrayOfData;
        17. }
        18. }
        コードをコピー
        オブザーバー (オブザーバーモード)

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

        1. interface Observer {
        2. function onChanged($sender, $args);
        3. }
        4. interface Observable {
        5. function addObserver($observer);
        6. }
        7. class CustomerListimplements Observable {
        8. private $_observers = array();
        9. public function addCustomer($name) {
        10. foreach($this->_observers as $obs)
        11. $obs->onChanged($this, $name);
        12. }
        13. public function addObserver($observer) {
        14. $this->_observers []= $observer;
        15. }
        16. }
        17. class CustomerListLogger は Observer を実装します {
        18. public function onChanged($sender, $args) {
        19. echo( "'$ args の顧客がリストに追加されました n" );
        20. }
        21. }
        22. $ul = new UserList();
        23. $ul->addObserver( new CustomerListLogger() );
        24. $ul->addCustomer( " Jack" );
        コードをコピー
        責任の連鎖 (責任の連鎖モデル)

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

        1. interface Command {
        2. function onCommand($name, $args);
        3. }
        4. class CommandChain {
        5. private $_commands = array();
        6. public function addCommand($cmd) {
        7. $this->_commands[]= $cmd;
        8. }
        9. public function runCommand($name, $args) {
        10. foreach($this->_commands as $cmd) {
        11. if ($cmd-> ;onCommand($name, $args))
        12. return;
        13. }
        14. }
        15. }
        16. class CustCommand は Command を実装します {
        17. public function onCommand($name, $args) {
        18. if ($name != 'addCustomer')
        19. return false;
        20. echo("これは 'addCustomer'n を処理する CustomerCommand です");
        21. return true;
        22. }
        23. }
        24. class MailCommand は Command {
        25. public function onCommand($name, $args) {
        26. if ($name) を実装します!= 'mail')
        27. return false;
        28. echo("これは 'mail'n を処理する MailCommand です");
        29. return true;
        30. }
        31. }
        32. $cc = new CommandChain();
        33. $cc->addCommand ( new CustCommand());
        34. $cc->addCommand( new MailCommand());
        35. $cc->runCommand('addCustomer', null);
        36. $cc->runCommand('mail', null) ;
        コードをコピー
    PHP


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