PHP 实战之设计模式:PHP 中的设计模式

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

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

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

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

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

Singleton(单例模式)
单例模式是最常见的模式之一,在Web应用的开发中,常常用于允许在运行时为某个特定的类创建一个可访问的实例。

final class Product{

    private static $instance;

    public $min;

    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->min = "firstProduct min";
$secondProduct->min = "secondProduct min";
echo $firstProduct->min;
echo PHP_EOL;
echo $secondProduct->min;

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

abstract class FactoryAbstract{

    private static $instances = array();

    public static function getInstance(){
        $className = static::getClassName();
        if(!isset(self::$instances[$className]) || !(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();
    }
}



abstract class Factory extends FactoryAbstract{

    public static function getInstance() {
        return parent::getInstance();
    }

    public static function removeInstance() {
        parent::removeInstance();
    }
}


class FirstProduct extends Factory{

    public $a = [];

}


class SecondProduct extends Factory{

    public $a = [];

}

FirstProduct::getInstance()->a[] = 1;
SecondProduct::getInstance()->a[] = 2;
FirstProduct::getInstance()->a[] = 3;
SecondProduct::getInstance()->a[] = 4;
var_dump(FirstProduct::getInstance()->a);
echo PHP_EOL;
var_dump(SecondProduct::getInstance()->a);

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

class Package{


    protected static $data  = array();

    public static function set($key, $val){
        self::$data[$key] = $val;        
    }

    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("uname", "Jack");
print_r(Package::get("uname"));

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

interface Factory{

    public function getProduct();
}

interface Product{

    public function getName();
}


class FristProduct implements Product{

    public function getName() {
        return "firstProduct name is pear";
    }

}


class SecondProduct implements Product{

    public function getName(){
        return "secondProduct name is bannelar";
    }
}

class FristFactory implements Factory{

    public function getProduct() {
        return new FristProduct();
    }    
}

class SecondFactory implements Factory{

    public function getProduct() {
        return new SecondProduct();
    }
}
$firstFactory = new FristFactory();
$firstProduct = $firstFactory->getProduct();
var_dump($firstProduct->getName());
$secondFactory = new SecondFactory;
var_dump($secondFactory->getProduct()->getName());

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

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 FristFactory();
                break;
            case 2:
                return new SecondFactory();
                break;

        }
        throw new Exception("Bad Config");
    }


    abstract public function getProduct();

}



class FristFactory extends AbstractFactory{

    public function getProduct() {
        return new FristProduct();
    }

}


class SecondFactory extends AbstractFactory{

    public function getProduct() {
        return new SecondProduct();
    }

}

class FristProduct implements Product{

    public function getName(){
        return "fristProduct getName";
    }

}

class SecondProduct implements Product{

    public function getName(){
        return "secondProduct getName";
    }

}

$firstProduct = AbstractFactory::getFactory()->getProduct();
Config::$factory = 2;
$secondProduct = AbstractFactory::getFactory()->getProduct();

var_dump($firstProduct->getName());
echo PHP_EOL;
echo PHP_EOL;
var_dump($secondProduct->getName());

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

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"));
echo Factory::getProduct("first")->getId();
echo PHP_EOL;
echo Factory::getProduct("second")->getId();

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

interface Product{

   public function getName(); 

}

class FirstProduct implements Product{

   public function getName(){
       return "firstProduct getName";
   } 

}


class SecondProduct implements Product{

   public function getName(){
       return "secondProduct 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;
    }
}

$factory = new Factory();
echo $factory->getFirstProduct()->getName();
echo PHP_EOL;
echo $factory->getSecondProduct()->getName();
echo PHP_EOL;
echo $factory->getFirstProduct()->getName();

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

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 = "firstProduct name";

$secondProduct = $prototypeFactory->getProduct();
$secondProduct->name = "secondProduct name";

var_dump($firstProduct->name);
echo PHP_EOL;
var_dump($secondProduct->name);

Builder(构造者)

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

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 builderProduct(){
        $this->product = new Product();
    }
}


class firstBuider extends Builder{

    public function builderProduct(){
        parent::builderProduct();
        $this->product->setName("i am is first product name");
    }

}

class secondBuider extends Builder{

    public function builderProduct(){
        parent::builderProduct();
        $this->product->setName("i am is second product name");
    }
}


class Factory{

    private $builder;

    public function __construct(Builder $builder) {
        $this->builder = $builder;
        $this->builder->builderProduct();
    }

    public function getProduct(){
        return $this->builder->getProduct();
    }
}




$Factory = new Factory(new firstBuider());
$firstProduct =   $Factory->getProduct();
echo $firstProduct->getName();
echo PHP_EOL;

$secondFactory = new Factory(new secondBuider());
$secondProduct = $secondFactory->getProduct();
echo $secondProduct->getName();

Decorator(装饰器模式)

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

class HtmlTempate{

}

class Template1 extends HtmlTempate{

    public $_html;

    public function __construct() {
        $this->_html = "<p>__TEXT__</p>";
    }

    public function setHtml($html){
        $this->_html = $html;
    }

    public function render(){
        echo $this->_html;
    }
}

class Template2 extends HtmlTempate{

    protected $_element;

    public function __construct($element) {
        $this->_element = $element;
        $this->setHtml("<h2>".$this->_element->_html."</h2>");
    }


    public function __call($name, $args) {
        $this->_element->$name($args[0]);
    }    
}

class Template3 extends HtmlTempate{

    protected $_element;

    public function __construct($element) {
        $this->_element = $element;
        $this->setHtml("<u>".$this->_element->_html."</u>");

    }

    public function __call($name, $args) {
        $this->_element->$name($args[0]);
    }
}
$Template1 = new Template1();
$Template2 = new Template2($Template1);
$Template3 = new Template3($Template1);
$Template1->render();

Adapter(适配器模式)

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

class SimpleBook{

    private $auther;
    private $title;

    public function __construct($auther, $title) {
        $this->auther = $auther;
        $this->title = $title;
    }

    public function getAuther(){
        return $this->auther;
    }

    public function getTitle(){
        return $this->title;
    }
}



class BookAdapter{

    private $book;

    public function __construct(SimpleBook $simple_book) {
        $this->book = $simple_book;
    }

    public function getAutherAndTitle(){
        return $this->book->getTitle()." by ".$this->book->getAuther();
    }
}


$bookAdapter = new BookAdapter(new SimpleBook("Jack", "hello work PHP"));
echo $bookAdapter->getAutherAndTitle();

Strategy(策略模式)

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

interface OutputInterface{   
    public function load();    
}

class SerializedArrayOutput implements OutputInterface{

    public $arrayOfData;


    public function load(){
        return serialize($this->arrayOfData);
    } 
}


class JsonStringOutput implements OutputInterface {

    public $arrayOfData;


    public function load() {
        return json_encode($this->arrayOfData);
    }
}


class ArrayOutput implements OutputInterface {

    public $arrayOfData;

    public function load() {
        return $this->arrayOfData;
    }
}



class TestOutput{

    private $data;

    private $output;

    public function __construct($data, OutputInterface $output) {
        $this->data = $data;
        $this->output = $output;
    }

    public function reande(){
        $this->output->arrayOfData = $this->data;
        return $this->output->load();
    }
}

$data = ["a","b","c","D"];
$testOutput = new TestOutput($data, new ArrayOutput());
var_dump($testOutput->reande());

$testOutput2 = new TestOutput($data, new JsonStringOutput());
var_dump($testOutput2->reande());

$testOutput3 = new TestOutput($data, new SerializedArrayOutput());
var_dump($testOutput3->reande());

Observer(观察者模式)

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

interface Observer {
  function onChanged($sender, $args);
}

interface Observable {
  function addObserver($observer);
}

class CustomerList implements Observable{

    private $_observers = array();

    public function addObserver($observer){
        $this->_observers[] = $observer;
    }

    public function addCustomer($name){

        foreach ($this->_observers as $obs){
            $obs->onChanged($this, $name);
        }
    }
}

class CustomerListLogger implements Observer{

    function onChanged($sender, $args){
         echo( "'$args' Customer has been added to the list \n" );
    }
}


$CustomerList = new CustomerList();
$CustomerList->addObserver(new CustomerListLogger());
$CustomerList->addCustomer("Jack");

Chain of responsibility(责任链模式)

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

interface Command{

    function onCommand($name, $args);

}


class CommandChain{


    private $_commands = array();

    public function addCommand($command){
        $this->_commands[] = $command;
    }

    public function runCommand($name, $args){
        foreach ($this->_commands as $command){
            if($command->onCommand($name,$args)){
                return;
            }
        }        
    }
}

class CustCommand implements Command{

    public function onCommand($name, $args){

        if($name !="addCoustomer"){
            return false;
        }
        echo ("This is CoustomerCommand and 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("mail", null);
$cc->runCommand("addCoustomer", null);
$cc->runCommand("update", null);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值