PHP工厂设计模式方法澄清

PHP Factory design pattern method clarification

我想知道本教程是否在PHP中正确实现了工厂设计模式。下面是实际的源代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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"

根据"四人帮"一书中的"设计模式",工厂模式的适用性是

  • 类不能预测它必须创建的对象的类
  • 类希望其子类指定它创建的对象
  • 类将责任委托给几个助手子类中的一个,您希望本地化哪些助手子类是委托的知识。

第一点,这个例子实际上知道要创建哪类对象,即Automobile,不是吗?

第二点,没有子类。Automobile类不从AutomobileFactory继承。我认为汽车制造厂应该至少有一个由汽车实现的功能,它处理对象的创建。

有人能解释清楚吗?我刚开始学习设计模式,每当我遇到不同于其他人的教程时,它会让我很困惑。


我非常同意维基百科的说法

  • The creation of an object precludes its reuse without significant duplication of code.
  • The creation of an object requires access to information or resources that should not be contained within the composing class.
  • The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.

我创建工厂的主要原因是我强调了这一点。

例如,让我们设想一个在全国拥有许多工厂的真实世界工厂。这家工厂生产门。门需要旋钮。由于物流原因,工厂的每一个工厂都有自己的旋钮供应商,另一个完全不同的工厂。

这个工厂的生产经理软件将根据一些标准来选择哪些工厂会生产很多门,但不需要知道旋钮从哪里来。选定的工厂将要求其自己的供应商为生产的门提供一个旋钮。

然而,对于客户来说,无论是哪家工厂制造的门,他只关心自己的门。

让我们把这个写在代码上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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();
    }
}

使用以下代码:

1
2
3
4
5
6
7
$manager = new ProductManager();
$manager->addPlant(new SaoPauloDoorFactory());
$manager->addPlant(new NewYorkDoorFactory());

$client  = new Client();

var_dump($client->getMyDoor($manager));

ProductManager对旋钮一无所知,Client对拥有多个工厂的工厂一无所知。


实际上有一个单一的工厂方法设计模式遵循原来的四人帮目录。抽象工厂是完全不同的,基于不同的结构假设。简单工厂不是设计模式,而是弗里曼所说的"编程习惯"。工厂方法包括抽象的创建者和产品,客户通常通过创建者提出他们的请求。具体工厂位于ConcreteCreator中,具体产品是产品类的子类,由具体的创建者实例化。有关完整和简单的PHP示例,请参阅http://www.php5dp.com/a-simple-php-design-pattern-the-factory-method/。


我和你在一起,Kidonchu,我不认为这个例子是传统的工厂方法模式。

我将这样编写您的示例(psuedo代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?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"


我不太喜欢这个教程。正如你在维基百科上看到的关于工厂的页面(https://en.wikipedia.org/wiki/factory_pattern)——通常情况下,它的做法是不同的。维基百科的例子确实符合你提到的规则。在那里查看php部分。