我想知道this tutorial是否正确地在PHP中实现工厂设计模式。以下是实际的源代码。
<?php
class Automobile
{
private $vehicle_make;
private $vehicle_model;
public function __construct($make, $model)
{
$this->vehicle_make = $make;
$this->vehicle_model = $model;
}
public function get_make_and_model()
{
return $this->vehicle_make . ' ' . $this->vehicle_model;
}
}
class AutomobileFactory
{
public static function create($make, $model)
{
return new Automobile($make, $model);
}
}
// have the factory create the Automobile object
$veyron = AutomobileFactory::create('Bugatti', 'Veyron');
print_r($veyron->get_make_and_model()); // outputs "Bugatti Veyron"
根据 Gang of Four 的书“设计模式”,工厂模式的适用性是
首先,这个例子实际上知道要创建哪个对象类,哪个是Automobile
,不是吗?
第二点,没有子类。 Automobile
类不会从AutomobileFactory
继承。我认为AutomobileFactory应该至少有一个由Automobile实现的功能,它处理对象创建。
有人可以澄清一下吗?我刚刚开始学习设计模式,每次遇到与其他人不同的教程时,都会让我感到困惑。
答案 0 :(得分:3)
我非常赞同维基百科中所说的内容
- 创建一个对象会阻止其重用,而不会出现重复的代码重复。
- 创建对象需要访问不应包含在撰写类中的信息或资源。
- 必须集中生成对象的生命周期管理,以确保应用程序内的一致行为。
我创建工厂的主要原因是我强调了这一点。
例如,让我们想象一下在全国各地有许多工厂的真实工厂。这家工厂生产门。门需要旋钮。出于物流原因,工厂的每个工厂都有自己的旋钮供应商,另一个完全不同的工厂。
这家工厂的生产经理软件会根据一些标准选择哪个工厂生产很多门,但不需要知道旋钮的来源。选定的工厂将要求自己的供应商提供生产门的旋钮。
然而,对于客户而言,哪个工厂开门并不重要,他只关心自己的门。
让我们把它放在代码上:
class Knob {
// something...
}
interface KnobSupplier {
public function makeKnob();
}
class SaoPauloKnobSupplier {
public function makeKnob() {
return new Knob('Knob made in São Paulo');
}
}
class NewYorkKnobSupplier {
public function makeKnob() {
return new Knob('Knob made in New York');
}
}
class Door {
public function __construct(Knob $knob) {
// something...
}
}
interface DoorFactory {
public function makeDoor();
}
class SaoPauloDoorFactory {
private $knobSupplier;
public function __construct() {
$this->knobSupplier = new SaoPauloKnobSupplier();
}
public function makeDoor() {
return new Door($this->knobSupplier->makeKnob(), "Door made in São Paulo");
}
}
class NewYorkDoorFactory {
private $knobSupplier;
public function __construct() {
$this->knobSupplier = new NewYorkKnobSupplier();
}
public function makeDoor() {
return new Door($this->knobSupplier->makeKnob(), "Door made in New York");
}
}
class ProductionManager {
private $plants = array();
// methods for adding plants, etc...
public function getDoor() {
// Somehow decides which plant will create the door.
return $plant->makeDoor();
}
}
class Client {
public function getMyDoor(ProductionManager $manager) {
return $manager->getDoor();
}
}
使用以下代码:
$manager = new ProductManager();
$manager->addPlant(new SaoPauloDoorFactory());
$manager->addPlant(new NewYorkDoorFactory());
$client = new Client();
var_dump($client->getMyDoor($manager));
ProductManager
对旋钮一无所知,Client
对工厂有一个以上工厂一无所知。
答案 1 :(得分:1)
我真的不喜欢这个教程。正如您在WikiPedia页面中看到的有关工厂(https://en.wikipedia.org/wiki/Factory_pattern)的信息 - 它通常以不同的方式完成。 WikiPedia示例符合您提到的规则。查看那里的PHP部分。
答案 2 :(得分:1)
我和你在一起Kidonchu,我并不认为这个例子是传统的工厂方法模式。
我会像这样编写你的例子(伪代码)
<?php
abstract class CarAbstract
{
protected $_vehicleMake;
protected $_vehicleModel;
public function __construct($model)
{
$this->_vehicleModel = $model;
}
public function getMakeAndModel()
{
return $this->_vehicleMake . ' ' . $this->_vehicleModel;
}
}
class Bugatti extends CarAbstract
{
public function __construct($model)
{
parent::__construct($model);
$this->_vehicleMake = get_class($this);
}
}
class AutomobileFactory
{
public static function getInstance($make, $model)
{
if (is_file('Model/Car/' . $make . '.php')){
require_once 'Model/Car/' . $make . '.php';
$car = new $make($model);
}else{
throw new Exception('Car not found');
}
}
}
$veyron = AutomobileFactory::getInstance('Bugatti', 'Veyron');
print_r($veyron->getMakeAndModel()); // outputs "Bugatti Veyron"
答案 3 :(得分:1)
实际上有一个工厂方法设计模式遵循原始的四个目录组。抽象工厂完全不同,基于不同的结构假设。简单工厂不是一种设计模式,而是Freemans所谓的“编程习语”。 Factory方法包括抽象的Creator和Product,客户端通常通过Creator提出请求。具体工厂位于ConcreteCreator中,具体产品是Product类的子类,由具体创建者实例化。有关完整而简单的PHP示例,请参阅http://www.php5dp.com/a-simple-php-design-pattern-the-factory-method/。