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