PHP常见的设计模式

设计模式六大原则

  • 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
  • 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象.
  • 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
  • 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
  • 接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
  • 迪米特法则:一个对象应该对其他对象保持最少的了解。

1.单例设计模式(Singleton)

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

应用场景:

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

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

单例类不能直接实例化创建,而是只能由类本身实例化。因此,要获得这样的限制效果,构造函数必须标记为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::$instance instanceof self)) {  
      self::$instance = new self();  
    }

return self::$instance;  
  }  
}

$a =Database::getInstance();  
$b =Database::getInstance();

// true  
var_dump($a === $b);

2.工厂设计模式

要是当操作类的参数变化时,只用改相应的工厂类就可以

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

使用场景:使用方法 new实例化类,每次实例化只需调用工厂类中的方法实例化即可。

优点:由于一个类可能会在很多地方被实例化。当类名或参数发生变化时,工厂模式可简单快捷的在工厂类下的方法中 一次性修改,避免了一个个的去修改实例化的对象。

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

例子

<?php

interface InterfaceShape   
{  
 function getArea();  
 function getCircumference();  
}

/** 
* 矩形 
*/  
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();

原文地址:https://www.cnblogs.com/myJuly/p/12686451.html

时间: 2024-10-13 07:29:06

PHP常见的设计模式的相关文章

JavaEE5种常见的设计模式

1.工厂模式:比如你写了个应用,里面用到了数据库的封装,你的应用可以今后需要在不同的数据库环境下运行,可能是oracle,db2,sql server等, 那么连接数据库的代码是不一样的,你用传统的方法,就不得不进行代码修改来适应不同的环境,非常麻烦,但是如果你采用工厂类的话,将各种 可能的数据库连接全部实现在工厂类里面,通过你配置文件的修改来达到连接的是不同的数据库,那么你今后做迁移的时候代码就不用进行修改了. 2.单例模式:提供了唯一实例的受控访问,对于经常要创建和销毁的对象单例模式无疑可以

javascript常见的设计模式举例

    近日重读<javascript面型对象编程指南>这本书,最后一章介绍了常见的javascript设计模式的实现.主要讲解了四种设计模式:单例模式.工厂模式.装饰器模式和观察者模式.js作为动态语言,实现这四种模式的实例相对简单,当然既然称之为模式,那么吃透思想更重要,那么下面,由乐帝来实例讲解四种模式.    1.单例模式    顾名思义,对象构造出来的是实例,从字面上理解,单例即单实例,这意味一个类只能创建一个实例对象.当需要创建一种类型或者一个类的唯一对象时,可使用该模式.以下两个

常见的设计模式:单例模式、工厂模式、观察者模式、装饰模式与适配器模式

常见的设计模式:单例模式.工厂模式.观察者模式.装饰模式与适配器模式 这里可以阅读Terry Lee的设计模式系列来理解学习一下 1.4.1 单例模式 .NET设计模式(2):单件模式(Singleton Pattern)  http://terrylee.cnblogs.com/archive/2005/12/09/293509.html 1.4.2 抽象工厂模式 .NET设计模式(3):抽象工厂模式(Abstract Factory) http://terrylee.cnblogs.com/

php中五种常见的设计模式

设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Gamma.Richard Helm.Ralph Johnson 和 John Vlissides Design(俗称 “四人帮”).所介绍的设计模式背后的核心概念非常简单.经过多年的软件开发实践,Gamma 等人发现了某些具有固定设计的模式,就像建筑师设计房子和建筑物一样,可以为浴室的位置或厨房的构造方式开发模板.使用这些模板或者说设计模式 意味着可以更快地设计更好的建筑物.同样的概念也适用于软件. 设计模式不仅代表着更快开发健壮

iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)

关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. 首先得搞清楚设计模式是个什么鬼,在软件设计领域,设计模式是对通用问题的可复用的解决方案.设计模式是一系列帮你写出更可理解和复用代码的模板,设计模式帮你创建松耦合的代码以便你不需要费多大力就可以改变或者替换代码中的组件 其实iOS中的设计模式有非常多,常用的就下面这四种 一.MVC设计模式(设计模式

Java中常见的设计模式

我在这里稍微总结一下Java中常见的一些设计模式. 1,单例设计模式 单例设计是Java中最常见的模式之一,,它就是要保证程序里边只有一个对象实例.就好比班上都叫他为班长,是因为得保证班上只有一个班长. 单例设计模式的程序设计思想反应的是Java面向对象思想的封装特性.就是为了保证只有一个对象实例,我们私有化它的构造函数,对外只提供一些相关的 公共方法来获得对象实例. 单例设计模式的实现主要分为饿汉式和懒汉式 饿汉式是先对类的对象实例化,随着类的加载对象也加载进来缺点是会造成性能的损耗好处是实现

Android中常见的设计模式

自己理解的设计模式遵循的原则: 1)功能单一明确,设计一个类的意图要明确,不能大包大揽什么功能都继承进去 2)对于扩展要开放,修改要关闭.软件通常都有需求变化,变化过程中通过扩展的方式来实现需求变化,而不是通过修改原有的方法,因为修改原有的方法会导致原来方法的调用方会出问题,这样层层调用出问题. 3)变化的进行抽象,不变的进行具体.设计代码过程中会面对很对可变的东西,比如在实现一个功能的时候,能够运用不同的方式进行实现,这个时候可以将每个具体的实现方法进行抽象,真正不变的是这个方法要实现的目的

Android开发中常见的设计模式

对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的同学,这里推荐2本书.一本是Head First系列的Head Hirst Design Pattern,英文好的可以看英文,可以多读几遍.另外一本是大话设计模式. 单例模式 首先了解一些单例模式的概念. 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 这样做有以下几个优点 对于

iOS常见的设计模式

ios开发学习中,经常弄不清楚ios的开发模式,今天我们就来进行简单的总结和探讨~ (一)代理模式 应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现.优势:解耦合敏捷原则:开放-封闭原则实例:tableview的 数据源delegate,通过和protocol的配合,完成委托诉求.列表row个数delegate自定义的delegate (二)观察者模式应用场景:一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息.优势: