生成器模式

在工厂方法模式的示例代码中,创建产品是一步成形(没有步骤)。生成器模式着重于将产品的创建过程分解为多个步骤,提供必选步骤和可选步骤。这些步骤是提供给外部代码(通常是 Director 类)使用的。

类图

2024061115531324.png

代码示例

<?php
 
// 产品
class Button
{
public $width;
public $height;
public $color = 'red';
 
public function render()
{
echo "Button: width: {$this->width}, height: {$this->height}, color: {$this->color}";
}
}
 
// 生成器
class ButtonBuilder
{
private $button;
 
public function __construct()
{
$this->button = new Button();
}
 
public function setWidth($width)
{
$this->button->width = $width;
}
 
public function setHeight($height)
{
$this->button->height = $height;
}
 
public function setColor($color)
{
$this->button->color = $color;
}
 
public function getButton(): Button
{
return $this->button;
}
}
 
// 指导者
class ButtonDirector
{
private $builder;
 
public function __construct(ButtonBuilder $builder)
{
$this->builder = $builder;
}
 
public function buildSmallRedButton()
{
$this->builder->setWidth(50);
$this->builder->setHeight(20);
}
 
public function buildBigBlackButton()
{
$this->builder->setWidth(100);
$this->builder->setHeight(40);
$this->builder->setColor('black');
}
}
 
// 客户端代码
$builder = new ButtonBuilder();
$director = new ButtonDirector($builder);
 
$director->buildSmallRedButton();
$button = $builder->getButton();
$button->render();
 
echo PHP_EOL;
 
$director->buildBigBlackButton();
$button = $builder->getButton();
$button->render();

如果有必要,可以把 ButtonBuilder 抽象为一个接口

生成器模式结合工厂方法模式

要引入工厂方法模式,则需要扩展产品,例如创建 WinButton 和 MacButton,因为工厂方法模式的其中一个作用就是为了创建多态产品。如果像上述代码,产品(Button)不具有多态性,则没有必要引入。

<?php
 
// 抽象产品
abstract class Button
{
public $width;
public $height;
public $color = 'red';
 
abstract public function render();
}
 
// win button 产品
class WinButton extends Button
{
public $color = 'blue';
 
public function render()
{
echo "Render a windows button with width: {$this->width}, height: {$this->height}, color: {$this->color}";
}
}
 
// mac button 产品
class MacButton extends Button
{
public $color = 'green';
 
public function render()
{
echo "Render a mac button with width: {$this->width}, height: {$this->height}, color: {$this->color}";
}
}
 
// 抽象生成器(抽象工厂)
interface ButtonBuilderInterface
{
public function setWidth($width);
public function setHeight($height);
public function setColor($color);
public function getButton(): Button;
}
 
// win button 生成器
class WinButtonBuilder implements ButtonBuilderInterface
{
private $button;
 
public function __construct()
{
$this->button = new WinButton();
}
 
public function setWidth($width)
{
$this->button->width = $width;
return $this;
}
 
public function setHeight($height)
{
$this->button->height = $height;
return $this;
}
 
public function setColor($color)
{
$this->button->color = $color;
return $this;
}
 
public function getButton(): Button
{
return $this->button;
}
}
 
// mac button 生成器
class MacButtonBuilder implements ButtonBuilderInterface
{
private $button;
 
public function __construct()
{
$this->button = new MacButton();
}
 
public function setWidth($width)
{
$this->button->width = $width;
return $this;
}
 
public function setHeight($height)
{
$this->button->height = $height;
return $this;
}
 
public function setColor($color)
{
$this->button->color = $color;
return $this;
}
 
public function getButton(): Button
{
return $this->button;
}
}
 
 
// 指导者
class ButtonDirector
{
private $builder;
 
public function __construct(ButtonBuilderInterface $builder)
{
$this->builder = $builder;
}
 
public function buildSmallRedButton()
{
$this->builder->setWidth(50);
$this->builder->setHeight(20);
}
 
public function buildBigBlackButton()
{
$this->builder->setWidth(100);
$this->builder->setHeight(40);
$this->builder->setColor('black');
}
}
 
 
// 客户端代码
$builder = new WinButtonBuilder();
$director = new ButtonDirector($builder);
$director->buildSmallRedButton();
$button = $builder->getButton();
$button->render();
 
echo PHP_EOL;
 
$builder = new MacButtonBuilder();
$director = new ButtonDirector($builder);
$director->buildBigBlackButton();
$button = $builder->getButton();
$button->render();