4

我想知道本教程是否在 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. 我认为汽车工厂应该至少有一个由汽车实现的功能,它处理对象的创建。

有人可以澄清一下吗?刚开始学习设计模式,每次遇到和别人不一样的教程,都让我很困惑。

4

4 回答 4

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一无所知,对拥有多个工厂的工厂一无所知。

于 2013-05-16T13:01:11.363 回答
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"
于 2013-05-16T11:59:49.543 回答
1

实际上有一个工厂方法设计模式遵循原始的四个目录。抽象工厂完全不同,并且基于不同的结构假设。简单工厂不是一种设计模式,而是弗里曼所说的“编程习惯”。Factory方法包括一个抽象的Creator和Product,Client一般通过Creator进行请求。具体的工厂位于 ConcreteCreator(s) 中,具体产品是 Product 类的子类,由具体创建者实例化。有关完整且简单的 PHP 示例,请参见http://www.php5dp.com/a-simple-php-design-pattern-the-factory-method/

于 2014-01-11T13:03:22.983 回答
1

我真的不喜欢这个教程。正如您在有关工厂的 WikiPedia 页面中看到的那样 ( https://en.wikipedia.org/wiki/Factory_pattern ) - 通常以不同的方式完成。WikiPedia 示例确实符合您提到的规则。查看那里的 PHP 部分。

于 2013-05-13T14:28:19.723 回答