- 相關(guān)推薦
PHP中的設(shè)計模式詳解
導(dǎo)語:設(shè)計模式并不是一種用來解釋的模式,它們并不是像鏈表那樣的常見的數(shù)據(jù)結(jié)構(gòu),也不是某種特殊的應(yīng)用或者框架設(shè)計。下面是PHP中的設(shè)計模式詳解,一起來學(xué)習(xí)下吧:
設(shè)計模式的解釋如下:
descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.
另一方面,設(shè)計模式提供了一種廣泛的可重用的方式來解決我們?nèi)粘>幊讨谐3S鲆姷膯栴}。設(shè)計模式并不一定就是一個類庫或者第三方框架,它們更多的表現(xiàn)為一種思想并且廣泛地應(yīng)用在系統(tǒng)中。它們也表現(xiàn)為一種模式或者模板,可以在多個不同的場景下用于解決問題。設(shè)計模式可以用于加速開發(fā),并且將很多大的想法或者設(shè)計以一種簡單地方式實現(xiàn)。當(dāng)然,雖然設(shè)計模式在開發(fā)中很有作用,但是千萬要避免在不適當(dāng)?shù)膱鼍罢`用它們。
目前常見的設(shè)計模式主要有23種,根據(jù)使用目標(biāo)的不同可以分為以下三大類:
創(chuàng)建模式:用于創(chuàng)建對象從而將某個對象從實現(xiàn)中解耦合。
架構(gòu)模式:用于在不同的對象之間構(gòu)造大的對象結(jié)構(gòu)。
行為模式:用于在不同的對象之間管理算法、關(guān)系以及職責(zé)。
Creational Patterns
Singleton(單例模式)
單例模式是最常見的模式之一,在Web應(yīng)用的開發(fā)中,常常用于允許在運行時為某個特定的類創(chuàng)建一個可訪問的實例。
/** * 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
在很多情況下,需要為系統(tǒng)中的多個類創(chuàng)建單例的構(gòu)造方式,這樣,可以建立一個通用的抽象父工廠方法:
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)
Registry
注冊臺模式并不是很常見,它也不是一個典型的創(chuàng)建模式,只是為了利用靜態(tài)方法更方便的存取數(shù)據(jù)。
/**
* 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(工廠模式)
工廠模式是另一種非常常用的模式,正如其名字所示:確實是對象實例的生產(chǎn)工廠。某些意義上,工廠模式提供了通用的方法有助于我們?nèi)カ@取對象,而不需要關(guān)心其具體的內(nèi)在的實現(xiàn)。
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
AbstractFactory(抽象工廠模式)
有些情況下我們需要根據(jù)不同的選擇邏輯提供不同的構(gòu)造工廠,而對于多個工廠而言需要一個統(tǒng)一的抽象工廠:
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
Object pool(對象池)
對象池可以用于構(gòu)造并且存放一系列的對象并在需要時獲取調(diào)用:
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
Lazy Initialization(延遲初始化)
對于某個變量的延遲初始化也是常常被用到的,對于一個類而言往往并不知道它的哪個功能會被用到,而部分功能往往是僅僅被需要使用一次。
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
Prototype(原型模式)
有些時候,部分對象需要被初始化多次。而特別是在如果初始化需要耗費大量時間與資源的時候進行預(yù)初始化并且存儲下這些對象。
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(構(gòu)造者)
構(gòu)造者模式主要在于創(chuàng)建一些復(fù)雜的對象:
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
Structural Patterns
Decorator(裝飾器模式)
裝飾器模式允許我們根據(jù)運行時不同的情景動態(tài)地為某個對象調(diào)用前后添加不同的行為動作。
class HtmlTemplate {
// any parent class methods
}
class Template1 extends HtmlTemplate {
protected $_html;
public function __construct() {
$this->_html = "
__text__
"; } 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("
" . $this->_html . "
"); } 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("" . $this->_html . ""); } public function __call($name, $args) { $this->_element->$name($args[0]); } } Adapter(適配器模式)
這種模式允許使用不同的接口重構(gòu)某個類,可以允許使用不同的調(diào)用方式進行調(diào)用:
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."
"; }
Behavioral Patterns
Strategy(策略模式)
測試模式主要為了讓客戶類能夠更好地使用某些算法而不需要知道其具體的實現(xiàn)。
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;
}
}
Observer(觀察者模式)
某個對象可以被設(shè)置為是可觀察的,只要通過某種方式允許其他對象注冊為觀察者。每當(dāng)被觀察的對象改變時,會發(fā)送信息給觀察者。
interface Observer { function onChanged($sender, $args); }
【PHP中的設(shè)計模式詳解】相關(guān)文章:
交互設(shè)計的用戶行為模式詳解06-24
PHP快速排序算法詳解08-30
PHP源代碼方式詳解08-08
php摘要生成函數(shù)詳解09-02
PHP對象Object的概念詳解09-05
php數(shù)據(jù)類型詳解09-24
PHP7的異常處理詳解08-16