写点什么

创建型设计模式 - 建造者 Builder

作者:菜皮日记
  • 2023-09-08
    北京
  • 本文字数:2228 字

    阅读完需:约 7 分钟

简介

建造者模式可将对象的初始化转变成一步步配置的过程。如当对象的初始化时有很多可选参数,建造者模式可以定制参数实现对象的创建。好处有:

  1. 定制对象参数

  2. 针对不同参数,做不同的校验,如当设置了三角形的两个边长,设置第三个边时必须满足两边之和大于第三边的条件。

角色

  • Builder 类

    定义建造一个 Product 分几个步骤

  • 具体 Builder 类

    实现不同的步骤

  • Director

    属于快速建造某一种产品的方法,如 Director 提供了创建自动挡和手动挡汽车两种方法,创建自动挡汽车中其实是调用 setA setB,而创建自动单汽车中调用 setC setD。也可以不使用 Director,直接使用 Builder 的 setA setB 去设置属性

  • 要被实例化的类

    初始化时可定制的参数较多,如 setA setB setC...

类图

图中的 Director 在 make 方法中封装了设置产品属性的步骤,通过传入不同的 builder 类,实现不同的实现步骤,创建不同的产品。

类图

代码

interface Builder{    public function producePartA(): void;
    public function producePartB(): void;
    public function producePartC(): void;}
class ConcreteBuilder1 implements Builder{    private $product;
    public function __construct()    {        $this->reset();    }
    public function reset(): void    {        $this->product = new Product1();    }
    public function producePartA(): void    {        $this->product->parts[] = "PartA1";    }
    public function producePartB(): void    {        $this->product->parts[] = "PartB1";    }
    public function producePartC(): void    {        $this->product->parts[] = "PartC1";    }
    public function getProduct(): Product1    {        $result = $this->product;        $this->reset();
        return $result;    }}
/** * EN: It makes sense to use the Builder pattern only when your products are * quite complex and require extensive configuration. * * Unlike in other creational patterns, different concrete builders can produce * unrelated products. In other words, results of various builders may not * always follow the same interface. * * RU: Имеет смысл использовать паттерн Строитель только тогда, когда ваши * продукты достаточно сложны и требуют обширной конфигурации. * * В отличие от других порождающих паттернов, различные конкретные строители * могут производить несвязанные продукты. Другими словами, результаты различных * строителей могут не всегда следовать одному и тому же интерфейсу. */class Product1{    public $parts = [];
    public function listParts(): void    {        echo "Product parts: " . implode(', ', $this->parts) . "\n\n";    }}
class Director{    private $builder;
    public function setBuilder(Builder $builder): void    {        $this->builder = $builder;    }
    public function buildMinimalViableProduct(): void    {        $this->builder->producePartA();    }
    public function buildFullFeaturedProduct(): void    {        $this->builder->producePartA();        $this->builder->producePartB();        $this->builder->producePartC();    }}
function clientCode(Director $director){    $builder = new ConcreteBuilder1();    $director->setBuilder($builder);
    echo "Standard basic product:\n";    $director->buildMinimalViableProduct();    $builder->getProduct()->listParts();
    echo "Standard full featured product:\n";    $director->buildFullFeaturedProduct();    $builder->getProduct()->listParts();
    // 不使用 Director,直接操作 builder 来创建产品    echo "Custom product:\n";    $builder->producePartA();    $builder->producePartC();    $builder->getProduct()->listParts();}
$director = new Director();clientCode($director);
复制代码

output:

Standard basic product:Product parts: PartA1
Standard full featured product:Product parts: PartA1, PartB1, PartC1
Custom product:Product parts: PartA1, PartC1
复制代码


用户头像

菜皮日记

关注

全干程序员 2018-08-08 加入

还未添加个人简介

评论

发布
暂无评论
创建型设计模式-建造者 Builder_设计模式_菜皮日记_InfoQ写作社区