专栏首页决胜机器学习设计模式专题(七)——建造者模式

设计模式专题(七)——建造者模式

设计模式专题(七)——建造者模式

(原创内容,转载请注明来源,谢谢)

一、概述

建造者模式(Builder),又称生成器模式,是将一个复杂的对象的构建与它的表示进行分离,使得同样构建的过程可以获取不同的表示,即可以通过构建过程中输入的参数不同,获取不同的构建结果,但是构建出来的内容必须包含的元素一定会存在。

使用建造者模式,用户只需要输入建造类型,就可以获取所需要的结果,而不用关心具体的构造细节。这样做的好处在于,当实现某个内容,需要的操作步骤很多,就可以通过建造者模式来进行统筹控制,而不会遗漏、错误使用某些过程。

二、类图

三、优点

1、封装性,使用建造者模式可以使客户端不必知道服务端的实现细节。

2、建造者独立,容易扩展。

3、便于控制细节风险,由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

四、对比

1、建造者模式与工厂模式

与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。

因此,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。

2、建造者模式与装饰模式

两者最根本的区别,在于装饰模式是用户可以对装饰的流程进行管控,根据需要进行不同的装饰,即需要在客户端对结果进行装饰;建造者模式更像是提供接口,根据客户端传入的建造方式,而调用服务端内部已经定义好的既定流程,返回一个建造的结果。

装饰模式的工作流程变化性更大,并且没有固定的建造流程,而是根据需要去进行“装饰”。而建造者模式,对于执行流程有比较固定的要求,虽然允许先后执行顺序不同、传入参数不同,但是大体上还是会构建出相似的结果。

因此,当添加(职能)的时候,可以用装饰模式。而当需要按照既定程序完成任务时,则考虑采用构建者模式。

五、使用场景

执行顺序——由于建造者模式是在建造者类中,根据客户端要求,进行各步骤的操作。因此,当同样的操作,不同的先后顺序,会得到不一样的结果,则可以用建造者模式。

1、实现业务

现要实现数据库的增删改操作(查询操作和增删改不太一样,因此不在放在此建造者模式中),则可以将三个操作封装在不同的方法中,并且调用一个建造者实现操作过程。

1)公共的操作,固定的流程

无论增删改的哪一种,都会按照下面的流程执行:

a.判断数据库连接情况,如果没有连接则连接数据库

b.拼接sql

拼接sql为三种操作有所区别的地方,但也有相同的地方可以提取,包括确定表格,确定where条件(修改和删除需要),确定改动字段(新增和修改需要),确定改动的值(新增和修改需要)

c.执行sql,并获取返回结果(新增返回last_insert_id,修改和删除返回affect_rows)

d.判断执行结果,如果成功,将sql语句、操作人员、操作时间记录数据库操作日志;如果失败,将失败的报错信息、sql语句、操作时间、操作人员记录数据库错误日志。

f.如果需要数据库操作的原子性,则事务操作beginTransaction和commit、rollback也是公共的操作。

2)独有的操作

a.新增

新增需要传入一个数组,包括字段和新增后的值的对应关系。

b.修改

修改需要传入两个数组,一个数组是类似新增的,字段和修改后的值的对应关系;另一个是where条件数组,包括字段和对应的where条件。

c.删除

删除需要传入一个数字,类似修改的where数组,包括字段和对应的where条件。

d.互不相同之处

拼接的sql语法不同。

2、实现方式

<?php
//建造者模式
//建造者抽象类,定义规则
abstract class SqlBuilder{
         public function__construct($type, array $arrData1=array(), array $arrData2=array()){}
         public functiongetConnection($server='localhost', $username='root', $password='root',$database='test'){}
         private functionbindSql($query, $arrData){}
         public functioninsert($table, array $arrData){}
         public functionupdate($table, array $arrData, array $arrWhere){}
         public functiondelete($table, array $arrWhere){}
         public functionstartTrans(){}
         public functioncommitTrans(){}
         public functionrollbackTrans(){}
}
//mysql实现的建造者
public function MysqlBuilder extends SqlBuilder{
         private $type;
         private $arrData;
         private $arrWhere;
         private $table;
         //根据传入的类型进行操作
         public function__construct($type, $table, array $arrData1, array $arrData2=array()){               
                   switch($type){
                            case'insert':
                                     $this->arrData= $arrData1;
                                     break;
                            case'update':
                                     if(empty($arrData2)){
                                               returnnull;
                                     }else{
                                               $this->arrData= $arrData1;
                                               $this->arrWhere= $arrData2;
                                     }
                                     break;
                            case'delete':
                                     $this->arrWhere= $arrData1;
                                     break;               
                            default:
                                     returnnull;
                                     break;
                   }
         }
         //连接数据库
         public functiongetConnection($server='localhost', $username='root', $password='root',$database='test'){
                   $dbConnection= new PDO('mysql:host='.$server.';dbname='.$database.'',$username,$password);
                   $dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
                   $dbConnection->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);                 
                   $this->conn= $dbConnection;
                   return$this;
         }
         //绑定值
         private functionbindSql($query, $arrData){
                   if(empty($arrData)){
                            returnnull;
                   }else{
                            foreach($arrDataas $col => &$val){
                                     $col= ':'.$col;
                                     $query->bindParam($col,$val);
                            }
                            return$query;
                   }                          
         }       
         //增删改的具体过程省略
         public functioninsert(){
                   //....
         }
         public functionupdate(){
                   //...
         }
         public functiondelete(){
                   //...
         }       
         //事务处理
         public functionstartTrans(){
                   $this->conn->beginTransaction();
                   return$this;
         }
         public functioncommitTrans(){
                   $this->conn->commit();
                   return$this;
         }
         public functionrollbackTrans(){
                   $this->conn->rollback();
                   return$this;             
         }       
}
//指挥者,负责完成操作
class Director{
         public function__construct(SqlBuilder $builder){
                   $type =$builder->type;
                   $builder =$builder->getConnection()->startTrans();
                   switch($type){
                            case'insert':
                                     $builder->insert();
                                     break;
                            case'update':
                                     $builder->update();
                                     break;
                            case'delete':
                                     $builder->delete();
                                     break;      
                            default:
                                     $builder->rollbackTrans();
                                     returnnull;
                                     break;
                   }
                   $builder->commit();
         }
}
//客户端,获取产品
$insertSql = new MysqlBuilder('insert', 'test',array('col1'=>'val1'));
$res = new Director($insertSql);

三、评价

建造者模式,实现客户端通过输入类型以及一些参数,获取建造的结果,而屏蔽各类细节。既可以规范的控制建造流程,又简化客户端的操作。

但是,实际项目中,通常数据库的增删改的操作,用到PHP的工作单元的知识,另外还涉及标记映射的知识。这块的内容是项目最常用到的方式,近期将针对数据库的增删改操作,运用工作单元的方式,进行项目级的实现。

——written by linhxx 2017.08.01

相关阅读:

设计模式专题(六)——原型模式

设计模式专题(五)——工厂方法模式

设计模式专题(四)——代理模式

设计模式专题(三)——装饰模式

设计模式专题(二)——策略模式

设计模式专题(一)——面向对象的设计原则

本文分享自微信公众号 - 决胜机器学习(phpthinker),作者:linhxx

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-08-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式专题(十二)——状态模式

    设计模式专题(十二)——状态模式 (原创内容,转载请注明来源,谢谢) 一、概述 状态模式(State)是指当一个对象的内在状态改变时允许改变其行为,这个对象看...

    用户1327360
  • PHP开发过程的那些坑(三) ——PHParray_shift函数

    PHP开发过程的那些坑(三)——PHP array_shift函数 (原创内容,转载请注明来源,谢谢) 坑: 最近在自学数据结构,常常用PHP实现各种数据结构...

    用户1327360
  • PHP PDO——单例模式实现数据库操作

    PHP PDO——单例模式实现数据库操作 (原创内容,转载请注明来源,谢谢) 一、概述 PDO是PHP访问数据库的轻量、持久的接口,其提供一个...

    用户1327360
  • 【php设计模式】装饰器模式

    装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能。其结构图如下:

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

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

    砸漏
  • Spring框架中的设计模式(三)

    在之前的两篇文章中,我们看到了一些在Spring框架中实现的设计模式。这一次我们会发现这个流行框架使用的3种新模式。 本文将从描述两个创意设计模式开始:原型和...

    程序猿DD
  • 浅析 .Net Core中Json配置的自动更新

    很早在看 Jesse 的Asp.net Core快速入门的课程的时候就了解到了在Asp .net core中,如果添加的Json配置被更改了,是支持自动重载配置...

    码农阿宇
  • 垂直电商架构进化之路

    作者:张增、邓良驹,分别为乐视云计算电商云团队负责人,乐视云计算高级开发工程师 来自:高效运维 1. 电商系统发展过程 电商网站在不同时期的架构复杂度有所不同:...

    架构师小秘圈
  • 【通信】XMLHttpRequest 代码说明

    示例中实例化了一个XMLHttpRequest对象,通过为该对象绑定onload回调函数处理从xxxUrl返回来的数据。

    Html5知典
  • apache工作模式梳理

    apache目前主要有两种模式:prefork模式和worker模式: 1)prefork模式(默认模式) prefork是Unix平台上的默认(缺省)MPM,...

    洗尽了浮华

扫码关注云+社区

领取腾讯云代金券