本文主要讨论下Web开发中,准确而言,是PHP开发中的相关的设计模式及其应用。有经验的开发者肯定对于设计模式非常熟悉,但是本文主要是针对那 些初级的开发者。首先我们要搞清楚到底什么是设计模式,设计模式并不是一种用来解释的模式,它们并不是像链表那样的常见的数据结构,也不是某种特殊的应用 或者框架设计。事实上,设计模式的解释如下:

descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.

另一方面,设计模式提供了一种广泛的可重用的方式来解决我们日常编程中常常遇见的问题。设计模式并不一定就是一个类库或者第三方框架,它们更多的表 现为一种思想并且广泛地应用在系统中。它们也表现为一种模式或者模板,可以在多个不同的场景下用于解决问题。设计模式可以用于加速开发,并且将很多大的想 法或者设计以一种简单地方式实现。当然,虽然设计模式在开发中很有作用,但是千万要避免在不适当的场景误用它们。

目前常见的设计模式主要有23种,根据使用目标的不同可以分为以下三大类:

  • 创建模式:用于创建对象从而将某个对象从实现中解耦合。
  • 架构模式:用于在不同的对象之间构造大的对象结构。
  • 行为模式:用于在不同的对象之间管理算法、关系以及职责。

Creational Patterns

Singleton(单例模式)

单例模式是最常见的模式之一,在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

在很多情况下,需要为系统中的多个类创建单例的构造方式,这样,可以建立一个通用的抽象父工厂方法:

 
 
<?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[] = ;
SecondProduct::getInstance()->a[] = ;
FirstProduct::getInstance()->a[] = ;
SecondProduct::getInstance()->a[] = ; print_r(FirstProduct::getInstance()->a);
// array(1, 3)
print_r(SecondProduct::getInstance()->a);
// array(2, 4)

Registry

注册台模式并不是很常见,它也不是一个典型的创建模式,只是为了利用静态方法更方便的存取数据。

 
 
<?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(工厂模式)

工厂模式是另一种非常常用的模式,正如其名字所示:确实是对象实例的生产工厂。某些意义上,工厂模式提供了通用的方法有助于我们去获取对象,而不需要关心其具体的内在的实现。

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

AbstractFactory(抽象工厂模式)

有些情况下我们需要根据不同的选择逻辑提供不同的构造工厂,而对于多个工厂而言需要一个统一的抽象工厂:

 
 
<?php

class Config {
public static $factory = ;
} interface Product {
public function getName();
} abstract class AbstractFactory { public static function getFactory() {
switch (Config::$factory) {
case :
return new FirstFactory();
case :
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 = ;
$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(对象池)

对象池可以用于构造并且存放一系列的对象并在需要时获取调用:

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

Lazy Initialization(延迟初始化)

对于某个变量的延迟初始化也是常常被用到的,对于一个类而言往往并不知道它的哪个功能会被用到,而部分功能往往是仅仅被需要使用一次。

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

Prototype(原型模式)

有些时候,部分对象需要被初始化多次。而特别是在如果初始化需要耗费大量时间与资源的时候进行预初始化并且存储下这些对象。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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(构造者)

构造者模式主要在于创建一些复杂的对象:

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

Structural Patterns

Decorator(装饰器模式)

装饰器模式允许我们根据运行时不同的情景动态地为某个对象调用前后添加不同的行为动作。

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

Adapter(适配器模式)

这种模式允许使用不同的接口重构某个类,可以允许使用不同的调用方式进行调用:

 
 
<?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/>";
}

Behavioral Patterns

Strategy(策略模式)

测试模式主要为了让客户类能够更好地使用某些算法而不需要知道其具体的实现。

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

Observer(观察者模式)

某个对象可以被设置为是可观察的,只要通过某种方式允许其他对象注册为观察者。每当被观察的对象改变时,会发送信息给观察者。

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

Chain of responsibility(责任链模式)

这种模式有另一种称呼:控制链模式。它主要由一系列对于某些命令的处理器构成,每个查询会在处理器构成的责任链中传递,在每个交汇点由处理器判断是否需要对它们进行响应与处理。每次的处理程序会在有处理器处理这些请求时暂停。

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

http://blog.jobbole.com/103565/

PHP 实战之设计模式:PHP 中的设计模式的更多相关文章

  1. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  2. [设计模式]JDK中的设计模式

    转载自:http://blog.csdn.net/gtuu0123/article/details/6114197 本文主要是归纳了JDK中所包含的设计模式,包括作用和其设计类图. 首先来个总结,具体 ...

  3. [Android]GOF23种设计模式 & Android中的设计模式

    GOF23种设计模式 设计原则: 1. 单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因 2. 开放-封闭原则(OCP):软件实体(类.模块.函数等)应该可以扩展,但是不可修改.即对 ...

  4. 访何红辉:谈谈Android源码中的设计模式

    最近Android 6.0版本的源代码开放下载,刚好分析Android源码的技术书籍<Android源码设计模式解析与实战>上市,我们邀请到它的作者何红辉,来谈谈Android源码中的设计 ...

  5. 初探Java设计模式4:一文带你掌握JDK中的设计模式

    转自https://javadoop.com/post/design-pattern 行为型模式 策略模式 观察者模式 责任链模式 模板方法模式 状态模式 行为型模式总结 本系列文章将整理到我在Git ...

  6. [Head First设计模式]山西面馆中的设计模式——观察者模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 引言 不知不自觉又将设计模式融入生活了,吃个饭也不得安生,也发现生活中的很多场景,都可以用设计模式来模拟.原来设计模式就在 ...

  7. [Head First设计模式]山西面馆中的设计模式——建造者模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 引言 将学习融入生活中,是件很happy的事情,不会感 ...

  8. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  9. [Head First设计模式]抢票中的设计模式——代理模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  10. Spring中的设计模式

    [Spring中的设计模式] http://www.uml.org.cn/j2ee/201301074.asp [详解设计模式在Spring中的应用]    [http://www.geek521.c ...

随机推荐

  1. 基础002_V7-CLB

    一.综述 参考ug474.pdf: 7系列中,一个CLB包含两个slice: 每个CLB的资源: CLB可配置的主要功能: 二.主要功能 LUT是基本单元,例如选择器assign muxout =  ...

  2. Zephir入门 —— 语法篇

    概述 Zephir的语法跟PHP很相似,所以这里不会把官网的文档照搬过来翻译一遍,而是会把一些Zephir相较于PHP比较特别的语法挑出来讲一下.如果想要要完整学习Zephir的语法,没有比官网的文档 ...

  3. 两table水平滚动条级联滚动(同步滚动)。 table1放标题,table2放内容。

    //table1=head和table2=body水平滚动条级联滚动 $(document).ready(function () { $("#bodyPanel").scroll( ...

  4. Android 自定义 View 知识点

    根据 Hencoder 提供的知识点,进行学习和总结. 三个要点: 布局 绘制 触摸反馈 绘制 自定义绘制:由自己实现绘制过程 常用绘制方法 onDraw(Canvas canvas) 绘制关键: c ...

  5. 我用Xamarin开发android应用,应用在真机上一打开就退出了

    在解决方案管理器的项目上右键--属性--Android Options--Packaging将Use Shared Runtime前面的对勾取消即可.

  6. Atitit js canvas的图像处理类库attilax总结与事业

    Atitit js canvas的图像处理类库attilax总结与事业 1.1. 脸部识别JavaScript类库Tracking.js1 1.2. AlloyImage特性1 1.3. CamanJ ...

  7. Atitit atiplat_reader 基于url阅读器的新特性

    Atitit atiplat_reader 基于url阅读器的新特性 1.1. feature功能特性1 1.2. note1 1.1. feature功能特性 支持url数据源,实际就是只支持一层连 ...

  8. 88个 Linux 系统管理员必备的监控工具

    随着互联网行业的不断发展,各种监控工具多得不可胜数.这里列出网上最全的监控工具.让你可以拥有超过80种方式来管理你的机器.在本文中,我们主要包括以下方面: 命令行工具 网络相关内容 系统相关的监控工具 ...

  9. 行为类模式(二):命令(Command)

    定义 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. UML 优点 能比较容易的设计一个命令队列 可以较容易的将命令加入日志 ...

  10. Centos6.9安装JDK1.8

    https://blog.csdn.net/zhangjm123/article/details/80784930