侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

PHP设计模式之建造者模式(Builder)原理与用法案例详解

php  /  管理员 发布于 7年前   163

本文实例讲述了PHP设计模式之建造者模式(Builder)原理与用法。分享给大家供大家参考,具体如下:

这个建造者模式,我们也可以称为生成器模式,核心思想是将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式,简单点来说就是为了消除其它对象复杂的创建过程。

例如:汽车,他的发动机引擎有好多品牌,轮胎也有各种材质,内饰更是千奇百怪;鸟,他的头、翅膀以及脚有各种颜色和形状,在创建这种复杂对象的时候,我们建议使用建造者模式。

先来看一个案例来感受下什么是建造者模式:

  1. 有一个用户的UserInfo类,创建这个类,需要创建用户的姓名,年龄,金钱等信息,才能获得用户具体的信息结果。
  2. 创建一个UserInfoBuilder 用户建造者类,这个类,将UserInfo复杂的创建姓名,年龄,金钱等操作封装起来,简化用户类的创建过程

完事代码如下:

//建造者模式,目的是消除其它对象复杂的创建过程/* 描述一个用户的类,包含用户姓名,年龄,金钱 */class UserInfo {    protected $userName = '';     protected $userAge = '';    protected $userMoney = '';    public function setUserName($userName) {        $this->userName = $userName;    }    public function setUserAge($userAge) {        $this->userAge = $userAge;    }    public function setUserMoney($userMoney) {        $this->userMoney = $userMoney;    }    public function getPeople() {        echo "这个人的姓名是:" . $this->setUserName . ',年龄是:' . $this->userAge . ', 金钱:' . $this->userMoney;    }}/* 实例化,并且创建这个用户的时候,是很痛苦的,需要设置用户名,年龄和金钱*/$peopleInfo = array(    'userName' => 'initphp',    'userAge' => 28,    'userMoney' => '100元'    );$UserInfo = new UserInfo;//下面需要一步步的设置用户信息,才能得到用户详细信息,过程纠结而痛苦$UserInfo->setUserName($peopleInfo['userName']); $UserInfo->setUserAge($peopleInfo['userAge']);$UserInfo->setUserMoney($peopleInfo['userMoney']);$UserInfo->getPeople();
//UserInfoBuilder 用户信息建造者类,将UserInfo的创建过程封装掉,开发者使用起来心情舒畅obj = new UserInfo;    }    public function buildPeople($peopleInfo) {        $this->obj->setUserName($peopleInfo['userName']);        $this->obj->setUserAge($peopleInfo['userAge']);        $this->obj->setUserMoney($peopleInfo['userMoney']);    }     public function getPeople() {        $this->obj->getPeople();    }}/* 创建过程被封装了,用户使用简单了 */$peopleInfo = array(    'userName' => 'initphp',    'userAge' => 28,    'userMoney' => '100元'    );$UserInfoBuilder = new UserInfoBuilder;$UserInfoBuilder->buildPeople($peopleInfo); //直接一个build$UserInfoBuilder->getPeople();

大概了解了之后,咱们就来继续看。

一般情况下,建造者模式一般有以下四种角色:

     1.产品角色,产品角色定义自身的组成属性

     2.抽象建造者,抽象建造者定义了产品的创建过程以及如何返回一个产品

     3.具体建造者,具体建造者实现了抽象建造者创建产品过程的方法,给产品的具体属性进行赋值定义

     4.指挥者,指挥者负责与调用客户端交互,决定创建什么样的产品

这四个角色也可以按照如下方式来理解:

  1. 抽象建造者(Builder)角色:定义一个抽象接口,规范产品各个组成成分的建造(即规范具体建造者的方法实现)。其中所规范的方法中必须包括建造方法和结果返回方法
  2. 具体建造者(ConcreteBuilder)角色:实现抽象建造者角色所定义的方法。具体建造者与业务逻辑关联性较大,应用程序最终会通过调用此角色中所实现的建造方法按照业务逻辑创建产品,在建造完成后通过结果返回方法返回建造的产品实例。一般在外部由客户或一个抽象工厂创建。
  3. 导演者(Director)角色:此角色的作用是调用具体的建造者角色建造产品。导演者与产品类没有直接关系,与产品类交谈的是具体抽象角色。
  4. 产品(Product)角色:在指导者的指导下由建造者所创建的那个复杂的对象导演者角色与客户端直接打交道,它理解客户端的业务逻辑,将客户端创建产品的请求拆分成对产品组成部分的请求,然后调用具体产品角色执行建造操作。它分离了客户端与具体建造者。

再来看个实例:

_head}
"; echo "翅膀的颜色:{$this->_wing}
"; echo "脚的颜色:{$this->_foot}
"; }}/**抽象鸟的建造者(生成器) * Class BirdBuilder */abstract class BirdBuilder{ protected $_bird; function __construct() { $this->_bird=new Bird(); } abstract function BuildHead(); abstract function BuildWing(); abstract function BuildFoot(); abstract function GetBird();}/**具体鸟的建造者(生成器) 蓝鸟 * Class BlueBird */class BlueBird extends BirdBuilder{ function BuildHead() { // TODO: Implement BuilderHead() method. $this->_bird->_head="Blue"; } function BuildWing() { // TODO: Implement BuilderWing() method. $this->_bird->_wing="Blue"; } function BuildFoot() { // TODO: Implement BuilderFoot() method. $this->_bird->_foot="Blue"; } function GetBird() { // TODO: Implement GetBird() method. return $this->_bird; }}/**玫瑰鸟 * Class RoseBird */class RoseBird extends BirdBuilder{ function BuildHead() { // TODO: Implement BuildHead() method. $this->_bird->_head="Red"; } function BuildWing() { // TODO: Implement BuildWing() method. $this->_bird->_wing="Black"; } function BuildFoot() { // TODO: Implement BuildFoot() method. $this->_bird->_foot="Green"; } function GetBird() { // TODO: Implement GetBird() method. return $this->_bird; }}/**指挥者 * Class Director */class Director{ /** * @param $_builder 建造者 * @return mixed 产品类:鸟 */ function Construct($_builder) { $_builder->BuildHead(); $_builder->BuildWing(); $_builder->BuildFoot(); return $_builder->GetBird(); }}//调用代码header("Content-Type:text/html;");//------------------------生成器模式测试代码------------------require_once "./Builder/Builder.php";$director=new Director();echo "蓝鸟的组成:
";$blue_bird=$director->Construct(new BlueBird());$blue_bird->Show();echo "
Rose鸟的组成:
";$rose_bird=$director->Construct(new RoseBird());$rose_bird->Show();

建造者模式它的优点很明显,就是它可以很好的将一个对象的实现与相关的“业务”逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易,缺点也是同样,那就是建造者接口的修改会导致所有执行类的修改。

关于这个建造者模式,它还有以下三个扩展模式:

  1. 抽象工厂模式(abstract factory模式):在抽象工厂模式中,每一次工厂对象被调用时都会返还一个完整的产品对象,而客户端可能会将这些产品组装成一个更大更复杂的产品,也可能不会。建造者模式则不同,它一点一点地建造出一个复杂的产品,而这个产品的组装过程发生在建造者内部。二者的区别在于是否有组装过程,组装过程发生的位置。这两个设计模式可以连起来用,客户端通过调用一个建造角色,间接调用另一个抽象工厂模式的工厂角色。工厂模式返还不同产品族的零件,而建造者模式则把它们组装起来。
  2. 策略模式(strategy模式):建造者模式在结构上很接近于策略模式,事实上建造者模式是策略模式的一种特殊情况。二者的区别在于用意不同。建造者模式作用于客户端一点一点的建造新的对象,而策略模式的目的是为算法提供抽象的接口。
  3. 建造者模式与模板方法模式:建造者模式在退化、失去导演者角色后,可以发展到模板方法模式(即将建造过程的算法实现放在建造角色中)。

以下情况应当使用建造者模式:

   1、 需要生成的产品对象有复杂的内部结构。
   2、 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
   3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。

使用建造者模式主要有以下效果:

   1、 建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
   2、 每一个Builder都相对独立,而与其它的Builder无关。
   3、 模式所建造的最终产品更易于控制。

咱们接下来,来尝试设计一个车的组装过程,这个是网上经典的案例,如下:

name = $name;  }  public function setEngine($engine)  {    $this->engine = $engine;  }  public function setChassis($chassis)  {    $this->chassis = $chassis;  }  public function setBody($body)  {    $this->body = $body;  }  public function setEquipment($equipment)  {    $this->equipment = $equipment;  }  public function show()  {    echo "名称:".$this->name."\r\n";    echo "引擎:".$this->engine."\r\n";    echo "底盘:".$this->chassis."\r\n";    echo "车身:".$this->body."\r\n";    echo "电子设备:".$this->equipment."\r\n";  }}/*}}}*///builderinterface IBuilder{/*{{{*/  public function builderName();  public function builderEngine();  public function builderChassis();  public function builderBody();  public function builderEquipment();  public function getCar();}/*}}}*///红旗车builderclass RedBuilder implements IBuilder{/*{{{*/  public $car;  public function __construct()  {    $this->car = new Car();  }  public function builderName()  {    $this->car->setName('红旗');   }  public function builderEngine()  {    $this->car->setEngine('国产发动机');   }  public function builderChassis()  {    $this->car->setChassis('超大底盘');   }  public function builderBody()  {    $this->car->setBody('超大');   }  public function builderEquipment()  {    $this->car->setEquipment('电子设备');   }  public function getCar()  {    return $this->car;  }}/*}}}*///QQ车builderclass QQBuilder implements IBuilder{/*{{{*/  public $car;  public function __construct()  {    $this->car = new Car();  }  public function builderName()  {    $this->car->setName('QQ');   }  public function builderEngine()  {    $this->car->setEngine('国产发动机');   }  public function builderChassis()  {    $this->car->setChassis('小底盘');   }  public function builderBody()  {    $this->car->setBody('小');   }  public function builderEquipment()  {    $this->car->setEquipment('电子设备');   }  public function getCar()  {    return $this->car;  }}/*}}}*///组装者(director)class CarDirector{/*{{{*/  public function make(IBuilder $builder)  {    $builder->builderName();    $builder->builderEngine();    $builder->builderChassis();    $builder->builderBody();    $builder->builderEquipment();    return $builder->getCar();  }}/*}}}*/class Client{/*{{{*/  public static function main($argv)  {    $director = new CarDirector();     $redBuilder = new RedBuilder();    $car = $director->make($redBuilder);    $car->show();    echo "\r\n";    $qqBuilder = new QQBuilder();    $car = $director->make($qqBuilder);    $car->show();  }}/*}}}*/Client::main($argv);?>

咱们可以观察到,建造者模式与工厂模式是极为相似的,并且总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色,在建造者模式中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。

与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类――导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。

好啦,本次记录就到这里了。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

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

您可能感兴趣的文章:

  • php设计模式 Builder(建造者模式)
  • 学习php设计模式 php实现建造者模式
  • PHP设计模式之建造者模式定义与用法简单示例
  • php设计模式之抽象工厂模式分析【星际争霸游戏案例】
  • php设计模式之工厂方法模式分析【星际争霸游戏案例】
  • php面向对象基础详解【星际争霸游戏案例】
  • PHP设计模式之观察者模式(Observer)详细介绍和代码实例
  • php设计模式 Template (模板模式)
  • php设计模式 DAO(数据访问对象模式)
  • php设计模式 Proxy (代理模式)
  • php设计模式之建造器模式分析【星际争霸游戏案例】


  • 上一条:
    PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
    下一条:
    PHP设计模式之适配器模式(Adapter)原理与用法详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客