PHP设计模式之建造者模式(Builder)原理与用法案例详解
本文实例讲述了PHP设计模式之建造者模式(Builder)原理与用法。分享给大家供大家参考,具体如下:
这个建造者模式,我们也可以称为生成器模式,核心思想是将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式,简单点来说就是为了消除其它对象复杂的创建过程。
例如:汽车,他的发动机引擎有好多品牌,轮胎也有各种材质,内饰更是千奇百怪;鸟,他的头、翅膀以及脚有各种颜色和形状,在创建这种复杂对象的时候,我们建议使用建造者模式。
先来看一个案例来感受下什么是建造者模式:
- 有一个用户的UserInfo类,创建这个类,需要创建用户的姓名,年龄,金钱等信息,才能获得用户具体的信息结果。
- 创建一个UserInfoBuilder用户建造者类,这个类,将UserInfo复杂的创建姓名,年龄,金钱等操作封装起来,简化用户类的创建过程
完事代码如下:
//建造者模式,目的是消除其它对象复杂的创建过程
/*描述一个用户的类,包含用户姓名,年龄,金钱*/
classUserInfo{
protected$userName='';
protected$userAge='';
protected$userMoney='';
publicfunctionsetUserName($userName){
$this->userName=$userName;
}
publicfunctionsetUserAge($userAge){
$this->userAge=$userAge;
}
publicfunctionsetUserMoney($userMoney){
$this->userMoney=$userMoney;
}
publicfunctiongetPeople(){
echo"这个人的姓名是:".$this->setUserName.',年龄是:'.$this->userAge.',金钱:'.$this->userMoney;
}
}
/*实例化,并且创建这个用户的时候,是很痛苦的,需要设置用户名,年龄和金钱*/
$peopleInfo=array(
'userName'=>'initphp',
'userAge'=>28,
'userMoney'=>'100元'
);
$UserInfo=newUserInfo;
//下面需要一步步的设置用户信息,才能得到用户详细信息,过程纠结而痛苦
$UserInfo->setUserName($peopleInfo['userName']);
$UserInfo->setUserAge($peopleInfo['userAge']);
$UserInfo->setUserMoney($peopleInfo['userMoney']);
$UserInfo->getPeople();
//UserInfoBuilder用户信息建造者类,将UserInfo的创建过程封装掉,开发者使用起来心情舒畅
obj=newUserInfo;
}
publicfunctionbuildPeople($peopleInfo){
$this->obj->setUserName($peopleInfo['userName']);
$this->obj->setUserAge($peopleInfo['userAge']);
$this->obj->setUserMoney($peopleInfo['userMoney']);
}
publicfunctiongetPeople(){
$this->obj->getPeople();
}
}
/*创建过程被封装了,用户使用简单了*/
$peopleInfo=array(
'userName'=>'initphp',
'userAge'=>28,
'userMoney'=>'100元'
);
$UserInfoBuilder=newUserInfoBuilder;
$UserInfoBuilder->buildPeople($peopleInfo);//直接一个build
$UserInfoBuilder->getPeople();
大概了解了之后,咱们就来继续看。
一般情况下,建造者模式一般有以下四种角色:
1.产品角色,产品角色定义自身的组成属性
2.抽象建造者,抽象建造者定义了产品的创建过程以及如何返回一个产品
3.具体建造者,具体建造者实现了抽象建造者创建产品过程的方法,给产品的具体属性进行赋值定义
4.指挥者,指挥者负责与调用客户端交互,决定创建什么样的产品
这四个角色也可以按照如下方式来理解:
- 抽象建造者(Builder)角色:定义一个抽象接口,规范产品各个组成成分的建造(即规范具体建造者的方法实现)。其中所规范的方法中必须包括建造方法和结果返回方法
- 具体建造者(ConcreteBuilder)角色:实现抽象建造者角色所定义的方法。具体建造者与业务逻辑关联性较大,应用程序最终会通过调用此角色中所实现的建造方法按照业务逻辑创建产品,在建造完成后通过结果返回方法返回建造的产品实例。一般在外部由客户或一个抽象工厂创建。
- 导演者(Director)角色:此角色的作用是调用具体的建造者角色建造产品。导演者与产品类没有直接关系,与产品类交谈的是具体抽象角色。
- 产品(Product)角色:在指导者的指导下由建造者所创建的那个复杂的对象导演者角色与客户端直接打交道,它理解客户端的业务逻辑,将客户端创建产品的请求拆分成对产品组成部分的请求,然后调用具体产品角色执行建造操作。它分离了客户端与具体建造者。
再来看个实例:
_head}
"; echo"翅膀的颜色:{$this->_wing}
"; echo"脚的颜色:{$this->_foot}
"; } } /**抽象鸟的建造者(生成器) *ClassBirdBuilder */ abstractclassBirdBuilder { protected$_bird; function__construct() { $this->_bird=newBird(); } abstractfunctionBuildHead(); abstractfunctionBuildWing(); abstractfunctionBuildFoot(); abstractfunctionGetBird(); } /**具体鸟的建造者(生成器)蓝鸟 *ClassBlueBird */ classBlueBirdextendsBirdBuilder { functionBuildHead() { //TODO:ImplementBuilderHead()method. $this->_bird->_head="Blue"; } functionBuildWing() { //TODO:ImplementBuilderWing()method. $this->_bird->_wing="Blue"; } functionBuildFoot() { //TODO:ImplementBuilderFoot()method. $this->_bird->_foot="Blue"; } functionGetBird() { //TODO:ImplementGetBird()method. return$this->_bird; } } /**玫瑰鸟 *ClassRoseBird */ classRoseBirdextendsBirdBuilder { functionBuildHead() { //TODO:ImplementBuildHead()method. $this->_bird->_head="Red"; } functionBuildWing() { //TODO:ImplementBuildWing()method. $this->_bird->_wing="Black"; } functionBuildFoot() { //TODO:ImplementBuildFoot()method. $this->_bird->_foot="Green"; } functionGetBird() { //TODO:ImplementGetBird()method. return$this->_bird; } } /**指挥者 *ClassDirector */ classDirector { /** *@param$_builder建造者 *@returnmixed产品类:鸟 */ functionConstruct($_builder) { $_builder->BuildHead(); $_builder->BuildWing(); $_builder->BuildFoot(); return$_builder->GetBird(); } } //调用代码 header("Content-Type:text/html;charset=utf-8"); //------------------------生成器模式测试代码------------------ require_once"./Builder/Builder.php"; $director=newDirector(); echo"蓝鸟的组成:
"; $blue_bird=$director->Construct(newBlueBird()); $blue_bird->Show(); echo"
Rose鸟的组成:
"; $rose_bird=$director->Construct(newRoseBird()); $rose_bird->Show();
建造者模式它的优点很明显,就是它可以很好的将一个对象的实现与相关的“业务”逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易,缺点也是同样,那就是建造者接口的修改会导致所有执行类的修改。
关于这个建造者模式,它还有以下三个扩展模式:
- 抽象工厂模式(abstractfactory模式):在抽象工厂模式中,每一次工厂对象被调用时都会返还一个完整的产品对象,而客户端可能会将这些产品组装成一个更大更复杂的产品,也可能不会。建造者模式则不同,它一点一点地建造出一个复杂的产品,而这个产品的组装过程发生在建造者内部。二者的区别在于是否有组装过程,组装过程发生的位置。这两个设计模式可以连起来用,客户端通过调用一个建造角色,间接调用另一个抽象工厂模式的工厂角色。工厂模式返还不同产品族的零件,而建造者模式则把它们组装起来。
- 策略模式(strategy模式):建造者模式在结构上很接近于策略模式,事实上建造者模式是策略模式的一种特殊情况。二者的区别在于用意不同。建造者模式作用于客户端一点一点的建造新的对象,而策略模式的目的是为算法提供抽象的接口。
- 建造者模式与模板方法模式:建造者模式在退化、失去导演者角色后,可以发展到模板方法模式(即将建造过程的算法实现放在建造角色中)。
以下情况应当使用建造者模式:
1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
使用建造者模式主要有以下效果:
1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个Builder都相对独立,而与其它的Builder无关。
3、模式所建造的最终产品更易于控制。
咱们接下来,来尝试设计一个车的组装过程,这个是网上经典的案例,如下:
name=$name;
}
publicfunctionsetEngine($engine)
{
$this->engine=$engine;
}
publicfunctionsetChassis($chassis)
{
$this->chassis=$chassis;
}
publicfunctionsetBody($body)
{
$this->body=$body;
}
publicfunctionsetEquipment($equipment)
{
$this->equipment=$equipment;
}
publicfunctionshow()
{
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";
}
}/*}}}*/
//builder
interfaceIBuilder
{/*{{{*/
publicfunctionbuilderName();
publicfunctionbuilderEngine();
publicfunctionbuilderChassis();
publicfunctionbuilderBody();
publicfunctionbuilderEquipment();
publicfunctiongetCar();
}/*}}}*/
//红旗车builder
classRedBuilderimplementsIBuilder
{/*{{{*/
public$car;
publicfunction__construct()
{
$this->car=newCar();
}
publicfunctionbuilderName()
{
$this->car->setName('红旗');
}
publicfunctionbuilderEngine()
{
$this->car->setEngine('国产发动机');
}
publicfunctionbuilderChassis()
{
$this->car->setChassis('超大底盘');
}
publicfunctionbuilderBody()
{
$this->car->setBody('超大');
}
publicfunctionbuilderEquipment()
{
$this->car->setEquipment('电子设备');
}
publicfunctiongetCar()
{
return$this->car;
}
}/*}}}*/
//QQ车builder
classQQBuilderimplementsIBuilder
{/*{{{*/
public$car;
publicfunction__construct()
{
$this->car=newCar();
}
publicfunctionbuilderName()
{
$this->car->setName('QQ');
}
publicfunctionbuilderEngine()
{
$this->car->setEngine('国产发动机');
}
publicfunctionbuilderChassis()
{
$this->car->setChassis('小底盘');
}
publicfunctionbuilderBody()
{
$this->car->setBody('小');
}
publicfunctionbuilderEquipment()
{
$this->car->setEquipment('电子设备');
}
publicfunctiongetCar()
{
return$this->car;
}
}/*}}}*/
//组装者(director)
classCarDirector
{/*{{{*/
publicfunctionmake(IBuilder$builder)
{
$builder->builderName();
$builder->builderEngine();
$builder->builderChassis();
$builder->builderBody();
$builder->builderEquipment();
return$builder->getCar();
}
}/*}}}*/
classClient
{/*{{{*/
publicstaticfunctionmain($argv)
{
$director=newCarDirector();
$redBuilder=newRedBuilder();
$car=$director->make($redBuilder);
$car->show();
echo"\r\n";
$qqBuilder=newQQBuilder();
$car=$director->make($qqBuilder);
$car->show();
}
}/*}}}*/
Client::main($argv);
?>
咱们可以观察到,建造者模式与工厂模式是极为相似的,并且总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色,在建造者模式中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。
与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
好啦,本次记录就到这里了。
更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。