ホームページ >バックエンド開発 >PHPチュートリアル >PHP実践デザインパターン [翻訳]
??> 元のアドレス:
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 nameFactory (ファクトリー パターン)
<?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 productAbstractFactory (抽象ファクトリ パターン)
<?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オブジェクト プール (オブジェクト プール)
<?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());// secondLazy Initialization (遅延初期化)
<?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 productPrototype (プロトタイプ モード)
<?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 productBuilder(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 パターン)
<?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" );責任の連鎖(責任連鎖モデル)
リーリー