php - 工厂方法 - 工厂可以/应该有几个创建同一个类的方法吗?
问题描述
假设我想建一所房子,我有一个房子工厂。工厂已经可以使用蓝图建造房屋。然而,一位新客户进来询问我们是否可以根据他们提供的草图为他们建造一所房子。在工厂里增加一条新的流水线来处理这些新房子是否正确?还是最好为草图建造的房屋建造一个全新的工厂?输出将始终是具有特定属性(即数量、颜色、屋顶)的房屋
class House_Factory {
public function create(Blueprint $blueprint) {
$house = new House();
$house->num_sides = $blueprint->num_sides;
$house->color = $blueprint->color;
$house->roof = $blueprint->roof;
return $house;
}
// Is having another create method acceptable in a Factory?
public function createFromSketch(Sketch $sketch) {
$house = new House();
$house->num_sides = $sketch->num_exterior_walls;
$house->color = $sketch->exterior_wall_color;
$house->roof = $sketch->roof;
return $house;
}
}
这对我来说似乎不对,但我不能把我的手指放在它上面。对于这种情况,是否有更好的设计模式可以遵循?
解决方案
在我看来,将这两种方法放在同一个类中是可以接受的。当您使用相同类型的输入创建不同的输出时,分解成不同的类(并实现接口)是有意义的——例如,如果您需要 make Houses
、Churches
和Sheds
,它们每个都有一个继承Building
接口的工厂,每个都有一个create
以 aBlueprint
作为参数的方法(其中Blueprint
可能是一个接口,每个具体工厂都需要它自己的变体Blueprint
等)。
让我觉得你的方法有点好笑的是你必须以create
不同的方式命名这些方法。在像 Java 这样的强类型语言中,您将有多种create
方法,由参数类型区分,这很好而且干净。
如果合适,您可以考虑的另一种方法是使用某种适配器将您的转换Sketches
为。Blueprints
<?php
class Blueprint
{
public $num_sides;
public $color;
public $roof;
public function __construct($num_sides, $color, $roof)
{
$this->num_sides = $num_sides;
$this->color = $color;
$this->roof = $roof;
}
}
class Sketch
{
public $num_exterior_walls;
public $exterior_wall_color;
public $roof;
public function __construct($num_exterior_walls, $exterior_wall_color, $roof)
{
$this->num_exterior_walls = $num_exterior_walls;
$this->exterior_wall_color = $exterior_wall_color;
$this->roof = $roof;
}
}
class House
{
public $num_sides;
public $color;
public $roof;
public function toString()
{
return json_encode([
'Sides' => $this->num_sides,
'Color' => $this->color,
'Roof' => $this->roof
]);
}
}
class HouseFactory
{
public function create(Blueprint $blueprint)
{
$house = new House();
$house->num_sides = $blueprint->num_sides;
$house->color = $blueprint->color;
$house->roof = $blueprint->roof;
return $house;
}
}
class BlueprintMapper
{
public static function fromSketch(Sketch $sketch)
{
return new Blueprint($sketch->num_exterior_walls, $sketch->exterior_wall_color, $sketch->roof);
}
}
$houseFactory = new HouseFactory();
$blueprint = new Blueprint(4, 'Red', 'Slate');
$house1 = $houseFactory->create($blueprint);
$sketch = new Sketch(4, 'Blue', 'Tin');
$sketchBlueprint = BlueprintMapper::fromSketch($sketch);
$house2 = $houseFactory->create($sketchBlueprint);
echo $house1->toString() . PHP_EOL;
echo $house2->toString() . PHP_EOL;
{"Sides":4,"Color":"Red","Roof":"Slate"}
{"Sides":4,"Color":"Blue","Roof":"Tin"}
推荐阅读
- react-native - 是否可以使用 BLE 在本机反应中检测/扫描三星 Galaxy Watch?
- html - 在 CSS 中从右侧滑入 DIV?酷蓝示例
- powershell - 计算机名称和主要用户配置文件的 PowerShell 列表
- mysql - MYSQL 唯一列
- r - R - 在我的数据框上使用 ungroup() 会破坏我的功能吗?
- javascript - 二叉搜索树中的删除如何在这里工作?
- python - 退出循环时字典中的列表为空
- powershell - Powershell 和 yaml 文件
- linux - 当我尝试使用 Cygwin 在 Windows 上交叉编译 Libcork 时出现错误(Windows 中存在类似版本的 ipset)
- java - Path.equals 在 Windows 和 Linux 上的行为不同