php常用几种设计模式的应用场景

原创 2016年08月29日 16:25:31


1.单例设计模式

所谓单例模式,即在应用程序中最多只有该类的一个实例存在,一旦创建,就会一直存在于内存中!

单例设计模式常应用于数据库类设计,采用单例模式,只连接一次数据库,防止打开多个数据库连接。

一个单例类应具备以下特点:

单例类不能直接实例化创建,而是只能由类本身实例化。因此,要获得这样的限制效果,构造函数必须标记为private,从而防止类被实例化。

需要一个私有静态成员变量来保存类实例和公开一个能访问到实例的公开静态方法。

在PHP中,为了防止他人对单例类实例克隆,通常还为其提供一个空的私有__clone()方法。

单例模式的例子:

<?php
  
/**
* Singleton of Database
*/
class Database
{
  // We need a static private variable to store a Database instance.
  privatestatic $instance;
  
  // Mark as private to prevent it from being instanced.
  private function__construct()
  {
    // Do nothing.
  }
  
  private function__clone() 
  {
    // Do nothing.
  }
  
  public static function getInstance() 
  {
    if (!(self::$instanceinstanceofself)) {
      self::$instance = newself();
    }
  
    returnself::$instance;
  }
}
  
$a =Database::getInstance();
$b =Database::getInstance();
  
// true
var_dump($a === $b);



2.工厂设计模式
主要是当操作类的参数变化时,只用改相应的工厂类就可以

工厂设计模式常用于根据输入参数的不同或者应用程序配置的不同来创建一种专门用来实例化并返回其对应的类的实例。

我们举例子,假设矩形、圆都有同样的一个方法,那么我们用基类提供的API来创建实例时,通过传参数来自动创建对应的类的实例,他们都有获取周长和面积的功能。

<?php
  
interface InterfaceShape 
{
 functiongetArea();
 functiongetCircumference();
}
  
/**
* 矩形
*/
class Rectangle implements InterfaceShape
{
  private $width;
  private $height;
   
  public function __construct($width, $height)
  {
    $this->width = $width;
    $this->height = $height;
  }
  
  public function getArea() 
  {
    return $this->width* $this->height;
  }
  
  public function getCircumference()
  {
    return 2 * $this->width + 2 * $this->height;
  }
}
  
/**
* 圆形
*/
class Circle implements InterfaceShape
{
  private $radius;
  
  function __construct($radius)
  {
    $this->radius = $radius;
  }
  
  
  public function getArea() 
  {
    return M_PI * pow($this->radius, 2);
  }
  
  public function getCircumference()
  {
    return 2 * M_PI * $this->radius;
  }
}
  
/**
* 形状工厂类
*/
class FactoryShape 
{ 
  public static function create()
  {
    switch (func_num_args()) {
      case1:
      return newCircle(func_get_arg(0));
      case2:
      return newRectangle(func_get_arg(0), func_get_arg(1));
      default:
        # code...
        break;
    }
  } 
}
  
$rect =FactoryShape::create(5, 5);
// object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) }
var_dump($rect);
echo "<br>";
  
// object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
$circle =FactoryShape::create(4);
var_dump($circle);


3.观察者设计模式

观察者模式是挺常见的一种设计模式,使用得当会给程序带来非常大的便利,使用得不当,会给后来人一种难以维护的想法。

什么是观察者模式?一个对象通过提供方法允许另一个对象即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!

<?php
  
/*
观察者接口
*/
interface InterfaceObserver
{
  function onListen($sender, $args);
  function getObserverName();
}
  
// 可被观察者接口
interface InterfaceObservable
{
  function addObserver($observer);
  function removeObserver($observer_name);
}
  
// 观察者抽象类
abstract class Observer implements InterfaceObserver
{
  protected $observer_name;
  
  function getObserverName() 
  {
    return $this->observer_name;
  }
  
  function onListen($sender, $args)
  {
  
  }
}
  
// 可被观察类
abstract class Observable implements InterfaceObservable 
{
  protected $observers = array();
  
  public function addObserver($observer) 
  {
    if ($observerinstanceofInterfaceObserver) 
    {
      $this->observers[] = $observer;
    }
  }
  
  public function removeObserver($observer_name) 
  {
    foreach ($this->observersas $index => $observer) 
    {
      if ($observer->getObserverName() === $observer_name) 
      {
        array_splice($this->observers, $index, 1);
        return;
      }
    }
  }
}
  
// 模拟一个可以被观察的类
class A extends Observable 
{
  public function addListener($listener) 
  {
    foreach ($this->observersas $observer) 
    {
      $observer->onListen($this, $listener);
    }
  }
}
  
// 模拟一个观察者类
class B extends Observer 
{
  protected $observer_name = 'B';
  
  public function onListen($sender, $args) 
  {
    var_dump($sender);
    echo "<br>";
    var_dump($args);
    echo "<br>";
  }
}
  
// 模拟另外一个观察者类
class C extends Observer 
{
  protected $observer_name = 'C';
  
  public function onListen($sender, $args) 
  {
    var_dump($sender);
    echo "<br>";
    var_dump($args);
    echo "<br>";
  }
}
  
$a = new A();
// 注入观察者
$a->addObserver(new B());
$a->addObserver(new C());
  
// 可以看到观察到的信息
$a->addListener('D');
  
// 移除观察者
$a->removeObserver('B');
  
// 打印的信息:
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
4.适配器模式
将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作。
应用场景:老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。例如:php连接数据库的方法:mysql,,mysqli,pdo,可以用适配器统一
//老的代码     

class User {    

    private $name;    

    function __construct($name) {    

        $this->name = $name;    

    }    

    public function getName() {    

        return $this->name;    

    }    

}   
//新代码,开放平台标准接口    

interface UserInterface {    

    function getUserName();    

}    

class UserInfo implements UserInterface {    

    protected $user;    

    function __construct($user) {    

        $this->user = $user;    

    }    

    public function getUserName() {    

        return $this->user->getName();    

    }    

}   
$olduser = new User('张三');    

echo $olduser->getName()."n";    

$newuser = new UserInfo($olduser);    

echo $newuser->getUserName()."n";    

5.策略模式
将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。
例如:一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告
MaleUserStrategy.php
<?php
 
namespace IMooc;


class MaleUserStrategy implements UserStrategy  {

    function showAd()
    {
        echo "IPhone6";
    }

    function showCategory()
    {
        echo "电子产品";
    }
} 
FemaleUserStrategy.php
<?php
 
namespace IMooc;

class FemaleUserStrategy implements UserStrategy {
    function showAd()
    {
        echo "2014新款女装";
    }
    function showCategory()
    {
        echo "女装";
    }
} 

UserStrategy.php
<?php
 
namespace IMooc;


interface UserStrategy {
    function showAd();
    function showCategory();
} 
<?php
interface FlyBehavior{
    public function fly();
}
 
class FlyWithWings implements FlyBehavior{
    public function fly(){
        echo "Fly With Wings \n";
    }
}
 
class FlyWithNo implements FlyBehavior{
    public function fly(){
        echo "Fly With No Wings \n";
    }
}
class Duck{
    private $_flyBehavior;
    public function performFly(){
        $this->_flyBehavior->fly();
    }
 
    public function setFlyBehavior(FlyBehavior $behavior){
        $this->_flyBehavior = $behavior;
    }
}
 
class RubberDuck extends Duck{
}
// Test Case
$duck = new RubberDuck();
 
/*  想让鸭子用翅膀飞行 */
$duck->setFlyBehavior(new FlyWithWings());
$duck->performFly();            
 
/*  想让鸭子不用翅膀飞行 */
$duck->setFlyBehavior(new FlyWithNo());
$duck->performFly();

6.装饰器模式
使用场景:当某一功能或方法draw,要满足不同的功能需求时,可以使用装饰器模式;实现方式:在方法的类中建addDecorator(添加装饰器),beforeDraw,afterDraw 3个新方法, 后2个分别放置在要修改的方法draw首尾.然后创建不同的装器类(其中要包含相同的,beforeDraw,afterDraw方法)能过addDecorator添加进去,然后在beforeDraw,afterDraw中循环处理,与观察者模式使用有点相似
1.装饰器模式(Decorator),可以动态地添加修改类的功能
2.一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法
3.使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性

DrawDecorator.php
<?php
namespace IMooc;

interface DrawDecorator
{
    function beforeDraw();
    function afterDraw();
}
Canvas.php
<?php
namespace IMooc;

class Canvas
{
    public $data;
    protected $decorators = array();

    //Decorator
    function init($width = 20, $height = 10)
    {
        $data = array();
        for($i = 0; $i < $height; $i++)
        {
            for($j = 0; $j < $width; $j++)
            {
                $data[$i][$j] = '*';
            }
        }
        $this->data = $data;
    }

    function addDecorator(DrawDecorator $decorator)
    {
        $this->decorators[] = $decorator;
    }

    function beforeDraw()
    {
        foreach($this->decorators as $decorator)
        {
            $decorator->beforeDraw();
        }
    }

    function afterDraw()
    {
        $decorators = array_reverse($this->decorators);
        foreach($decorators as $decorator)
        {
            $decorator->afterDraw();
        }
    }

    function draw()
    {
        $this->beforeDraw();
        foreach($this->data as $line)
        {
            foreach($line as $char)
            {
                echo $char;
            }
            echo "<br />\n";
        }
        $this->afterDraw();
    }

    function rect($a1, $a2, $b1, $b2)
    {
        foreach($this->data as $k1 => $line)
        {
            if ($k1 < $a1 or $k1 > $a2) continue;
            foreach($line as $k2 => $char)
            {
                if ($k2 < $b1 or $k2 > $b2) continue;
                $this->data[$k1][$k2] = ' ';
            }
        }
    }
}

ColorDrawDecorator.php
<?php
namespace IMooc;

class ColorDrawDecorator implements DrawDecorator
{
    protected $color;
    function __construct($color = 'red')
    {
        $this->color = $color;
    }
    function beforeDraw()
    {
        echo "<div style='color: {$this->color};'>";
    }
    function afterDraw()
    {
        echo "</div>";
    }
}

index.php
<?php
define('BASEDIR', __DIR__);
include BASEDIR.'/IMooc/Loader.php';
spl_autoload_register('\\IMooc\\Loader::autoload');
 
$canvas = new IMooc\Canvas();
$canvas->init();
$canvas->addDecorator(new \IMooc\ColorDrawDecorator('green'));
$canvas->rect(3,6,4,12);
$canvas->draw();





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

PHP八大设计模式

PHP命名空间可以更好地组织代码,与Java中的包类似。 Test1.php
  • flitrue
  • flitrue
  • 2016年09月21日 23:13
  • 8550

五种常见的 PHP 设计模式

工厂模式 最初在设计模式 一书中,许多设计模式都鼓励使用松散耦合。要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程。在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为...

4.php设计模式:状态模式的使用场景

在这儿给大家说点事儿。我的博客搬家到github主页上了。我的博客。以后首发都在github上了。csdn也会继续更新。可能就是稍微慢一下。另外最近搞了一个支付的开源项目。这是项目地址 目前已经支持...
  • hel12he
  • hel12he
  • 2016年06月30日 09:16
  • 670

五种常见的 PHP 设计模式

设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗称 “四人帮”)。所...

PHP设计模式之观察者模式(Observer)详细介绍和代码实例

【意图】 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新【GOF95】 又称为发布-订阅(Publish-Subscribe)模式、模型-视图...
  • longjef
  • longjef
  • 2016年11月02日 09:51
  • 2914

观察者模式应用场景实例

设计模式之PHP项目应用——策略模式设计商场收银系统

1 策略模式简介     策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。      2 模式组成     1)抽象策略角色(...

PHP SplQueue 队列简介

队列是一种特殊的线性表,遵循先进先出原则,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头...

PHP SPL的使用

转载自:http://my.oschina.net/kakoi/blog/522133 在许多框架和MVC中都能够看到PHP SPL的身影, PHP SPL 在很多实际应用都占了很大的比重 双...

各大主流编程语言比较,运用场景

摘要一个星期没写博客了,晚上看了别人写的博客及各大编程语言,突然发现自己尽管了解大部分编程语言,但对各个语言的运用场景及发展前景并不明晰,我想很多人也跟我一样,做一行,只了解本行的发展,但真正的市场趋...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:php常用几种设计模式的应用场景
举报原因:
原因补充:

(最多只允许输入30个字)