PHP工厂设计模式方法澄清

时间:2013-05-13 14:23:02

标签: php design-patterns factory factory-pattern

我想知道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实现的功能,它处理对象创建。

有人可以澄清一下吗?我刚刚开始学习设计模式,每次遇到与其他人不同的教程时,都会让我感到困惑。

4 个答案:

答案 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/