PHP设计模式之建造者

建造者模式,也可以叫做生成器模式,是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。

从建筑上来说,盖房子不是一下子就马上能把一个房子盖好的,而是通过一砖一瓦搭建出来的。一个房子不仅有砖瓦,还有各种管道,各种电线等等,由它们各个不部分共同组成了一栋房子。可以说,建造者模式就是这样非常形象的由各种部件来组成一个对象(房子)的过程。

建造者模式一般认为有四个角色:

  1. 产品角色,产品角色定义自身的组成属性
  2. 抽象建造者,抽象建造者定义了产品的创建过程以及如何返回一个产品
  3. 具体建造者,具体建造者实现了抽象建造者创建产品过程的方法,给产品的具体属性进行赋值定义
  4. 指挥者,指挥者负责与调用客户端交互,决定创建什么样的产品

优点:
生成不同形式的产品时, 你可以复用相同的制造代码。
单一职责原则。 你可以将复杂构造代码从产品的业务逻辑中分离出来。
缺点:
由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加。

代码:

<?php
// 产品角色
class User{
	protected $name = '';
	protected $age = '';
	protected $sex = '';
 
	public function setName($name){
		$this->name = $name;
	}
 
	public function setAge($age){
		$this->age = $age;
	}
 
	public function setSex($sex){
		$this->sex = $sex;
	}
 
	public function getUser(){
		echo '这个人姓名是:' . $this->name 
		. ',年龄是:' . $this->age
		. ',性别是:' . $this->sex .'。<br>';
	}
}
 
// 抽象建造者
interface UserBuilder{
	public function builderName();
	public function builderAge();
	public function builderSex(); 
	
	public function getUser();
}
 
// 具体建造者
class CommonBuilder implements UserBuilder{
	public $user;
 
	public function __construct(){
		$this->user = new User();
	}
 
	public function builderName(){
		$this->user->setName('普通用户');
	}
 
	public function builderAge(){
		$this->user->setAge('20');
	}
 
	public function builderSex(){
		$this->user->setSex('男');
	}
 
	public function getUser(){
		return $this->user;
	}
}
 
// 具体建造者
class SupperBuilder implements UserBuilder{
	public $user;
 
	public function __construct(){
		$this->user = new User();
	}
 
	public function builderName(){
		$this->user->setName('超级用户');
	}
 
	public function builderAge(){
		$this->user->setAge('30');
	}
 
	public function builderSex(){
		$this->user->setSex('女');
	}
 
	public function getUser(){
		return $this->user;
	}
}
 
// 指挥者
class UserDirector{
	public function make(UserBuilder $builder){
		$builder->builderName();
		$builder->builderAge();
		$builder->builderSex();
		return $builder->getUser();
	}
}
 
$director = new UserDirector();
$commonBuilder = new CommonBuilder();
$commonUser = $director->make($commonBuilder);
$commonUser->getUser();
 
$supperBuilder = new SupperBuilder();
$supperUser = $director->make($supperBuilder );
$supperUser->getUser();

在这里插入图片描述

建造者模式最好的应用方式之一是 SQL 查询生成器。 生成器接口定义了生成一般 SQL 查询所需的通用步骤。 另一方面, 对应不同 SQL 语言的具体生成器会去实现这些步骤, 返回能在特定数据库引擎中执行的 SQL 查询语句。

<?php

interface SQLQueryBuilder
{
	public function select(string $table, array $fields): SQLQueryBuilder;
	
	public function where(string $field, string $value, string $operator = '='): SQLQueryBuilder;
	
	public function limit(int $start, int $offset): SQLQueryBuilder;
	
	// +100 other SQL syntax methods...
	
	public function getSQL(): string;
}


class MysqlQueryBuilder implements SQLQueryBuilder
{
	protected $query;
	
	protected function reset(): void
	{
		$this->query = new \stdClass();
	}
	
	
	public function select(string $table, array $fields): SQLQueryBuilder
	{
		$this->reset();
		$this->query->base = "SELECT " . implode(", ", $fields) . " FROM " . $table;
		$this->query->type = 'select';
		
		return $this;
	}
	
	
	public function where(string $field, string $value, string $operator = '='): SQLQueryBuilder
	{
		if (!in_array($this->query->type, ['select', 'update', 'delete'])) {
			throw new \Exception("WHERE can only be added to SELECT, UPDATE OR DELETE");
		}
		$this->query->where[] = "$field $operator '$value'";
		
		return $this;
	}
	
	
	public function limit(int $start, int $offset): SQLQueryBuilder
	{
		if (!in_array($this->query->type, ['select'])) {
			throw new \Exception("LIMIT can only be added to SELECT");
		}
		$this->query->limit = " LIMIT " . $start . ", " . $offset;
		
		return $this;
	}
	
	
	public function getSQL(): string
	{
		$query = $this->query;
		$sql = $query->base;
		if (!empty($query->where)) {
			$sql .= " WHERE " . implode(' AND ', $query->where);
		}
		if (isset($query->limit)) {
			$sql .= $query->limit;
		}
		$sql .= ";";
		return $sql;
	}
}


class PostgresQueryBuilder extends MysqlQueryBuilder
{
	
	public function limit(int $start, int $offset): SQLQueryBuilder
	{
		parent::limit($start, $offset);
		
		$this->query->limit = " LIMIT " . $start . " OFFSET " . $offset;
		
		return $this;
	}
}


class app{
	public function make(SQLQueryBuilder $queryBuilder)
	{
		$query = $queryBuilder
			->select("users", ["name", "email", "password"])
			->where("age", 18, ">")
			->where("age", 30, "<")
			->limit(10, 20)
			->getSQL();
		
		echo $query,PHP_EOL;
	}
}

$app = new app();
$app->make(new MysqlQueryBuilder());
$app->make(new PostgresQueryBuilder());

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值