本文实例讲述了PHP设计模式之原型模式定义与用法。分享给大家供大家参考,具体如下:

原型设计模式(Prototype Design Pattern)很有意思, 因为它使用了一种克隆技术来复制实例化的对象. 新对象是通过复制原型实例来创建的. 在这里, 实例是批实例化的具体类.原型设计模式的目的是通过使用克隆来减少实例化对象的开销.与其从一个类实例化新对象, 完全可以使用一个已有实例的克隆.

克隆函数

PHP中使用原型设计模式的关键是要了解如何使用内置函数__clone().

<"handsome";
    $this->name = "chenqionghe";
  }
  public function display()
  {
    echo 'look : '.$this->face;;
    echo '<br />'.$this->name.'<br />';
  }
  public function __clone() {}
}
$boy = new Boy();
$boy->display();
$cloneBoy = clone $boy;
$cloneBoy->face = "still handsome";
$cloneBoy->display();

运行结果如下

look : handsome
chenqionghe
look : still handsome
chenqionghe

$cloneBoy实例是通过克隆Boy的实例$boy, 它可以像$boy一样访问相同的属性, 而且像Boy类的直接实例一样改变这些属性.

注意: 对于所克隆的实例 , clone关键字会为该实例的类实例化另一个实例(使用克隆关键字可以创建一个类的副本, 如果可能, 会自动调用对象的__clone方法, 但不能直接调用 对象的__clone方法), 关于过程, 有一点需要注意的是, 克隆不会不会启动构造函数中的动作.

简单的原型例子

我们以研究果蝇为例.研究的目标是建立一个原型果蝇, 然后一旦出现变异, 就构建这个变异果蝇

抽象类接口和具体实现

原型(IPrototype)的两个具体类实现分别表示不同性别的果蝇, 包括性别变量(gender)和不同性别的和行为.

IPrototype.php

<"htmlcode">
<"MALE";
  public $mated;
  public function __construct()
  {
    $this->eyeColor = "red";
    $this->winBeat = "220";
    $this->unitEypes = "760";
  }
  public function __clone(){}
}

FemaleProto.php

<"FEMAIL";
  public $fecundity;
  public function __construct()
  {
    $this->eyeColor = "red";
    $this->winBeat = "220";
    $this->unitEypes = "760";
  }
  public function __clone(){}
}

客户

在原型设计模式中,Clien类确实是一个不可缺少的部分.原因在于, 尽管要将子类具体实现作为实例的模板,但使用相同的模板克隆实例的具体工作是由Client类完成的

Client.php

<"true";
    $this->c2Fly->fecundity = '186';
    $this->updatedCloneFly->eyeColor = "purple";
    $this->updatedCloneFly->winBeat = "220";
    $this->updatedCloneFly->unitEyes = '750';
    $this->updatedCloneFly->fecundity = '92';
    //通过类型提示方法发送
    $this->showFly($this->c1Fly);
    $this->showFly($this->c2Fly);
    $this->showFly($this->updatedCloneFly);
  }
  private function showFly(IPrototype $fly)
  {
    echo "Eye color: ".$fly->eyeColor."<br />";
    echo "Wing Beats/second: ".$fly->winBeat."<br />";
    echo "Eye units: ".$fly->unitEypes."<br />";
    $genderNow = $fly::gender;
    echo "Gender: ".$genderNow."<br />";
    if($genderNow == "FEMAIL")
    {
      echo "Number of eggs: ".$fly->fecundity."<hr />";
    }
    else
    {
      echo "Mated: ".$fly->mated."<hr />";
    }
  }
}
$worker = new Client();

运行结果如下

Eye color: red
Wing Beats/second: 220
Eye units: 760
Gender: MALE
Mated: trueEye color: red
Wing Beats/second: 220
Eye units: 760
Gender: FEMAIL
Number of eggs: 186Eye color: purple
Wing Beats/second: 220
Eye units: 760
Gender: FEMAIL
Number of eggs: 92

原型模式要依赖客户通过 不念克隆过程使用具体原型.在这个设计过程中, 客户是完成克隆的参与者, 由于克隆是原型设计中的关键要素, 所以客户是一个基本参与者, 而不仅仅是一个请求类.

现代企业组织

在创建型设计模式方面,现代企业组织就非常适合原型实现.现在企业组织往往是复杂而庞大的层次结构, 像面向对象编程一样,要为很多共同的特征建模.现在通过一个例子描述软件工程公司.

软件工程公司是一个典型的现代组织.工程部(Engineering Department)负责创建产品,管理部(Management)处理资源的协调组织,市场部(Marketing)负责产品的销售,推广和整体营销.

接口中的封装

在这个原型实现中,首先为程序的接口(一个抽象类)增加OOP,与所有原型接口一样,这个接口包含一个克隆操作.另外它还包含一些抽象和具体的获取方法和设置方法.其中有一个抽象获取方法/设置方法对,但要由3个具体原型实现为这个抽象获取方法/设置方法对提供具体实现.其他获取方法和设置方法分分别应用于员工名,ID码和照片等属性.注意所有这些属性都是保护属性(protected),所以尽管具体的获取方法和设置方法有公共可见性,但由于操作中使用的属性具有保护和可见性,这就提供了某种程度的封装:

<"dept"抽象方法以及__clone()方法.类似地, 每个具体原型类还包含一个常量UNIT,它提供一个赋值,可以由实例(包括克隆的对象)作为标识

首先来看市场部的Marketing类:

Marketing.php

<"Marketing";
  private $sales = "sales";
  private $promotion = "promotion";
  private $strategic = "strategic planning";
  public function setDept($orgCode)
  {
    switch($orgCode)
    {
      case 101:
        $this->department = $this->sales;
        break;
      case 102:
        $this->department = $this->promotion;
        break;
      case 103:
        $this->department = $this->strategic;
        break;
      default :
        $this->department = "未识别的市场部";
    }
  }
  public function getDept()
  {
    return $this->department;
  }
  public function __clone() {}
}

setDept()方法的实现使用了一个参数.并不是直接输入市场部的部门,这个方法的参数是一个数字码, 通过一个switch语句,限制了3种可接受的情况和默认情况,别外两个原型实现也类似

Management.php

<"Management";
  private $research = "research";
  private $plan = "planning";
  private $operations = "operations";
  public function setDept($orgCode)
  {
    switch($orgCode)
    {
      case 201:
        $this->department = $this->research;
        break;
      case 202:
        $this->department = $this->plan;
        break;
      case 203:
        $this->department = $this->operations;
        break;
      default :
        $this->department = "未识别的管理部";
    }
  }
  public function getDept()
  {
    return $this->department;
  }
  public function __clone() {}
}

Engineering.php

<"Engineering";
  private $development = "development";
  private $design = "design";
  private $sysAd = "system administration";
  public function setDept($orgCode)
  {
    switch($orgCode)
    {
      case 301:
        $this->department = $this->development;
        break;
      case 302:
        $this->department = $this->design;
        break;
      case 303:
        $this->department = $this->sysAd;
        break;
      default :
        $this->department = "未识别的工程部";
    }
  }
  public function getDept()
  {
    return $this->department;
  }
  public function __clone() {}
}

以上这3个具体原型实现分别有其特定用途,不过它们都符合接口,可以创建各个原型实现的一个实例, 然后根据需要克隆多个实例.这个克隆的工作由Client类完成

客户

客户的设置非常简单: 分别创建各个具体原型的一个实例, 然后按以下列表来克隆各个实例:

市场部门实例:
-----市场部门克隆
-----市场部门克隆
管理部门实例
-----管理部门克隆
工程部门实例
-----工程部门克隆
-----工程部门克隆

将来只使用这些克隆对象.使用获取方法和设置方法将各个特定情况的信息赋给这些克隆对象.以下是Client的实现

Client.php

<"Tess Smith" , 101, 'ts101-1234', 'tess.png');
    $this->showEmployee($Tess);
    $Jacob = clone $this->market;
    $this->setEmployee($Jacob, "Jacob Jones" , 101, 'jj101-2234', 'jacob.png');
    $this->showEmployee($Jacob);
    $Ricky = clone $this->manage;
    $this->setEmployee($Ricky, "Ricky Rodriguez" , 203, 'rr101-5634', 'ricky.png');
    $this->showEmployee($Ricky);
    $Olivaia = clone $this->engineer;
    $this->setEmployee($Olivaia, "Olivaia Perez" , 302, 'op301-1278', 'olivia.png');
    $this->showEmployee($Olivaia);
    $John = clone $this->engineer;
    $this->setEmployee($John, "John Jacson" , 101, 'jj301-14548', 'john.png');
    $this->showEmployee($John);
  }
  private function makeConProto()
  {
    $this->market = new Marketing();
    $this->manage = new Management();
    $this->engineer = new Engineering();
  }
  private function showEmployee(IAcmePrototype $employeeNow)
  {
    $px = $employeeNow->getPic();
    echo "<img src=$px width='150' height='150' /><br />";
    echo $employeeNow->getName().'<br />';
    echo $employeeNow->getDept().':'.$employeeNow::UNIT.'<br />';
    echo $employeeNow->getId().'<hr />';
  }
  private function setEmployee(IAcmePrototype $employeeNow, $nm, $dp, $id, $px)
  {
    $employeeNow->setName($nm);
    $employeeNow->setDept($dp);
    $employeeNow->setId($id);
    $employeeNow->setPic($px);
  }
}
$worker = new Client();

解释:

客户Client的构造函数类包含3个私有属性, 用来分别实例化3个具体原型类. makeConPro()方法生成必要的实例.

接下来,使用克隆技术创建一个"员工"实例.然后,这个实例向一个设置方法setEmployee()发送特定的实例信息,这个设置方法使用IAcmePrototype接口类型提示,不过需要说明, 它只对第一个参数使用类型提示,其他参数都没有类型提示, 并不要求它们派生自IAcmePrototype接口.克隆"员工"可以使用IAcmePrototype抽象类的所有设置方法以及具体原型类实现的setDept()方法.

要使用各个员工的数据,Client类可以使用继承的获取方法.以下是运行Client输出的结果

Tess Smith
sales:Marketing
ts101-1234
Jacob Jones
sales:Marketing
jj101-2234
Ricky Rodriguez
operations:Management
rr101-5634
Olivaia Perez
design:Engineering
op301-1278
John Jacson
未识别的工程部:Engineering
jj301-14548

可以根据需要增加更多的克隆, 而且只需要对具体原型类完成一次实例化.使用原型模式时, 并不是建立具体类的多个实例,而只需要一个类实例化和多个克隆.

完成修改,增加特性

要记住,最重要(可能也是最基本)的是, 设计模式允许开发人员修改和增补程序,而不必一切从头开始.例如, 假设总裁决定公司增加一个新的部门,比如研究部门(Research), 这会很难吗"这有什么区别" 换句话说,为什么克隆比直接实例化对象需要的资源少"_blank" href="https://www.jb51.net/Special/43.htm">php面向对象程序设计入门教程》、《PHP基本语法入门教程》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

标签:
PHP,设计模式,原型模式

免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
狼山资源网 Copyright www.pvsay.com

评论“PHP设计模式之原型模式定义与用法详解”

暂无“PHP设计模式之原型模式定义与用法详解”评论...

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?