PHP中常见的设计模式

栏目: PHP · 发布时间: 9年前

内容简介:PHP中常见的设计模式

什么是设计模式?

在软件开发过程中,经常出现的经典场景的典型解决方案,称为设计模式

如何学习设计模式?

典型场景 --> 典型问题 --> 典型解决办法

1.多态

-------------------------------------------------------------------------------------------------------------------------------------

用来消除逻辑语句.

多态(ploymorphism)是一个生物学上的概念,指同一特种的多种表现形态.

在面向对象中,指某种对象实例的不同表现形态.


 
   

abstract class Tiger {
  public abstract function climb();
}

class XTiger extends Tiger {
  public function climb() {
    echo 'Drop' , '';
  }
}

class MTiger extends Tiger {
  public function climb() {
    echo 'Up' , '';
  }
}

class Cat {
  public function climb() {
    echo 'Fly';
  }
}

class Client {
  public static function call(Tiger $animal) { // 参数限定不严格,可以更加灵活, 可以传递一个父类类型,就可以有不同的子类形态
    $animal->climb();
  }
}

Client::call(new XTiger());
Client::call(new MTiger());
Client::call(new Cat());

?>

在23种 设计模式 中,可以有些模式可以自然消除的.

2.策略模式

-------------------------------------------------------------------------------------------------------------------------------------

在此模式中,算法是从复杂类提取的,因而可以方便地替换。例如,如果要更改搜索引擎中排列页的方法,则策略模式是一个不错的选择。思考一下搜索引擎的几个部分 —— 一部分遍历页面,一部分对每页排列,另一部分基于排列的结果排序。在复杂的示例中,这些部分都在同一个类中。通过使用策略模式,您可将排列部分放入另一个类中,以便更改页排列的方式,而不影响搜索引擎的其余代码。

PHP中常见的设计模式

//定义接口

interface IStrategy {

    function filter($record);

}

//实现接口方式1

class FindAfterStrategy implements IStrategy {

    private $_name;

    public function __construct($name) {

        $this->_name = $name;

    }

    public function filter($record) {

        return strcmp ( $this->_name, $record ) <= 0;

    }

}

//实现接口方式1

class RandomStrategy implements IStrategy {

    public function filter($record) {

        return rand ( 0, 1 ) >= 0.5;

    }

}

//主类

class UserList {

    private $_list = array ();

    public function __construct($names) {

        if ($names != null) {

            foreach ( $names as $name ) {

                $this->_list [] = $name;

            }

        }

    }

    

    public function add($name) {

        $this->_list [] = $name;

    }

    

    public function find($filter) {

        $recs = array ();

        foreach ( $this->_list as $user ) {

            if ($filter->filter ( $user ))

                $recs [] = $user;

        }

        return $recs;

    }

}

$ul = new UserList ( array (

        "Andy",

        "Jack",

        "Lori",

        "Megan" 

) );

$f1 = $ul->find ( new FindAfterStrategy ( "J" ) );

print_r ( $f1 );

$f2 = $ul->find ( new RandomStrategy () );

3.命令链模式

------------------------------------------------------------------------------------------------------------------------------------

命令链 模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容。每个处理程序都会自行判断自己能否处理请求。如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序,而不影响其他处理程序。清单 5 显示了此模式的一个示例。


 
   
interface ICommand
{
  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 UserCommand implements ICommand
{
  public function onCommand( $name, $args )
  {
    if ( $name != 'addUser' ) return false;
    echo( "UserCommand handling 'addUser'\n" );
    return true;
  }
}
 
class MailCommand implements ICommand
{
  public function onCommand( $name, $args )
  {
    if ( $name != 'mail' ) return false;
    echo( "MailCommand handling 'mail'\n" );
    return true;
  }
}
 
$cc = new CommandChain();
$cc->addCommand( new UserCommand() );
$cc->addCommand( new MailCommand() );
$cc->runCommand( 'addUser', null );
$cc->runCommand( 'mail', null );
?>

此代码定义维护 ICommand 对象列表的 CommandChain  类。两个类都可以实现 ICommand 接口 —— 一个对邮件的请求作出响应,另一个对添加用户作出响应。 

PHP中常见的设计模式

如果您运行包含某些测试代码的脚本,则会得到以下输出:

% php chain.php
UserCommand handling 'addUser'
MailCommand handling 'mail'
%

代码首先创建 CommandChain  对象,并为它添加两个命令对象的实例。然后运行两个命令以查看谁对这些命令作出了响应。如果命令的名称匹配 UserCommand 或 MailCommand,则代码失败,不发生任何操作。

为处理请求而创建可扩展的架构时,命令链模式很有价值,使用它可以解决许多问题。

4.工厂方法

-------------------------------------------------------------------------------------------------------------------------------------

进行扩展,避免对原有数据进行修改,只需要新增代码的子类,就可以完成。

对于修改是封闭的,对于扩展是开放的.


 
   


// 共同接口
// 数据库的接口
interface DB {
  function conn();
}

// 创造数据库的接口
interface Factory {
  function createDB();
}

// 服务端开发(不知道将会被谁调用)
class DbMysql implements DB {
  public function conn() {
    echo 'conn mysql 
'
; } } class DbSqlite implements DB { public function conn() { echo 'conn sqlite
'
; } } class MySqlFactory implements Factory { public function createDB() { return new DbMysql(); } } class SqliteFactory implements Factory { public function createDB() { return new DbSqlite(); } } // ==== 服务器端添加oracle类 // 进行扩展,避免对原有数据进行修改 class orcale implements DB { public function conn() { echo 'conn orcal
'
; } } class orcaleFactory implements Factory { public function createDB() { return new orcale(); } } // ------客户端开始调用. $fact = new MysqlFactory(); $db = $fact->createDB(); $db->conn(); $fact = new SqliteFactory(); $db = $fact->createDB(); $db->conn();

5.单列模式

-------------------------------------------------------------------------------------------------------------------------------------

常见使用场景:

  1. 需要数据库类的时候
  2. 操作cookie类
  3. 上传图片类
DB.class.php
Upload.class.php
Cookie.class.php
// 这三个类都需要读取配置文件信息,而配置文件是共用的,因此配置读取类有一个对象就够了。 
// (如何保证对象只有一个)

PHP对象什么时候全等

二个对象是一个的时候.

单例模式实现

  1. 封闭外部new操作
  2. 内部开公共接口,负责new操作,控制单一实例
  3. 禁止继承覆盖__construcotr
  4. 防止克隆
class Single {
   protected static $ins = null;
   public static function getIns() { // getIns的控制权在class内部,可以在getIns做手脚
     if (self::$ins === null) {
       self::$ins = new self();
     }
     return self::$ins;  // 返回自身实例
   } 
   final protected function __constructor() { // 方法前加 final,则方法不能被覆盖,类前加final,则类不能被继承。

   }

   // 封锁clone
   final protected function __clone() {

   }
}

$s1 = Single::getIns();
$s2 = clone $s1; // 克隆了,又产生了多个对象.

var_dump($s1, $s2);
var_dump($s1 === $s2); // true

6.观察者模式

-------------------------------------------------------------------------------------------------------------------------------------

一个对象变化,引起其它对象的反应。可以让其它几个对象观察变化的对象的反应.

一对多的关系.

优点:解耦。

观察者模式中的三者:Subject, Observer, Client;

// Subject
attach() // 记忆多个的对象
detach()  // 告知记忆的对象,变化情况
notify()  // 更新通知

// Observer
update() // 更新对象中执行的逻辑

// Client
// 调用添加观察者`attach()`

JavaScript实现观察者模式:

var select = document.querySelector('select');
var content = document.querySelector('.content');
var ad = document.querySelector('.ad');

// Subject
select.observer = {};
// 添加观察者
select.attach = function(key, obj) {
  this.observer[key] = obj;    
}

// 删除观察者
select.detach = function(key) {
  delete this.observer[key];
}

// 更新通知
select.onchange = select.ontify = function() {
  for (var key in this.observer) {
    this.observer[key].update(this);
  }
}

// Observer  
// 观察者
content.update = function(observer) { // 参数是被观察者对象
  alert('content');
  if (observer.value) {
    // 逻辑代码
  }
}

ad.update = function(observer) { // 参数是被观察者对象
  alert('ad');
  if (observer.value) {
    // 逻辑代码
  }
}


// Client
// 监听 
select.attach('content', content); // 只需要把独特的表示加入 对象key中
select.attach('ad', ad);

7.模版模式

-------------------------------------------------------------------------------------------------------------------------------------

模板模式准备一个抽象类,将部分逻辑以具体方法以及具体构造形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。

uml类图:

PHP中常见的设计模式

角色:

抽象模板角色(MakePhone):抽象模板类,定义了一个具体的 算法 流程和一些留给子类必须实现的抽象方法。

具体子类角色(XiaoMi):实现MakePhone中的抽象方法,子类可以有自己独特的实现形式,但是执行流程受MakePhone控制。

核心:


 
     
/** 
 * Created by PhpStorm-> 
 * User  extends  Jang 
 * Date  extends  2015/6/10 
 * Time  extends  11  extends 06 
 */  
  
//抽象模板类  
abstract class MakePhone  
{  
    protected $name;  
  
    public function __construct($name)  
    {  
        $this->name=$name;  
    }  
  
    public function MakeFlow()  
    {  
        $this->MakeBattery();  
        $this->MakeCamera();  
        $this->MakeScreen();  
        echo $this->name."手机生产完毕!
  
    
"
; } public abstract function MakeScreen(); public abstract function MakeBattery(); public abstract function MakeCamera(); } //小米手机 class XiaoMi extends MakePhone { public function __construct($name='小米') { parent::__construct($name); } public function MakeBattery() { echo "小米电池生产完毕!
"
; } public function MakeCamera() { echo "小米相机生产完毕!
"
; } public function MakeScreen() { echo "小米屏幕生产完毕!
"
; } } //魅族手机 class FlyMe extends MakePhone { function __construct($name='魅族') { parent::__construct($name); } public function MakeBattery() { echo "魅族电池生产完毕!
"
; } public function MakeCamera() { echo "魅族相机生产完毕!
"
; } public function MakeScreen() { echo "魅族屏幕生产完毕!
"
; } }

客户端测试代码;

header("Content-Type:text/html;charset=utf-8");  
//-------------------------模板模式---------------------  
require_once "./Template/Template.php";  
$miui=new XiaoMi();  
$flyMe=new FlyMe();  
  
$miui->MakeFlow();  
$flyMe->MakeFlow();

适用场景及优势:

1、完成某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时。我们通常考虑用模板模式来处理。

2、当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现,我们通过模板模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。

3、模板模式通过把不变的行为搬移到超级抽象类,去除子类中的重复代码来体现它的优势。模板模式提供了一个很好的代码复用平台

.....

.....

.....

.....

.....

over.....................................


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro JavaScript Design Patterns

Pro JavaScript Design Patterns

Dustin Diaz、Ross Harmes / Apress / 2007-12-16 / USD 44.99

As a web developer, you’ll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power......一起来看看 《Pro JavaScript Design Patterns》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具