首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >学习型工厂设计模式

学习型工厂设计模式
EN

Code Review用户
提问于 2020-10-10 19:19:14
回答 1查看 85关注 0票数 0

我正在制作一个非常常见的工厂设计模式的例子,它创建了一个汽车工厂,并返回了一个汽车实例。我在这里找到了一个例子,https://refactoring.guru/design-patterns/factory-method/php/example并决定建立我自己的工厂。我的问题是为什么每辆车我都需要一个造物主?

代码语言:javascript
复制
代码语言:javascript
复制
代码语言:javascript
复制
代码语言:javascript
复制
factoryMethod();
        // Now, use the product.
        $result = "I want to drive something..... " .
            $product->drive();

        return $result;
    }
}
代码语言:javascript
复制
代码语言:javascript
复制
代码语言:javascript
复制
someOperation();
    // ...
}

echo "The client . 
";
clientCode(new AudiCreator());
echo "\r\n";
echo  "
";
echo  "
";

clientCode(new MercedesCreator());
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-10-11 04:59:57

我想你是在想这件事。重点不在于您需要定义特殊的子类来使用工厂方法。相反,当需要定义包含自己复杂功能的特殊子类时,可以使用工厂方法。

来自四人帮

当一个类无法预测它必须创建的对象类时,使用Factory方法模式,希望它的子类指定它创建的类。

我认为问题的一部分是你自己的例子有点混乱。接口更多地用于定义不同对象可以完成的任务。您经常会听到人们将接口描述为一种契约,因为实现接口的任何对象都需要实现该接口的每个功能。Car将更符合逻辑地定义为类,因为奥迪和宝马是汽车的<#>type。另一方面,定义一个由抽象的Drivable类实现的Vehicle接口可能是有意义的。

代码语言:javascript
复制
interface Drivable
{
    public function drive();
}

然后,可以为实现此接口的每个泛型基对象类定义抽象基类。

代码语言:javascript
复制
abstract class Vehicle implements Drivable
{
    abstract public function drive();
}

一旦您这样做,那么您就可以为每个对象实现功能。

代码语言:javascript
复制
abstract class Car extends Vehicle
{
    abstract public function drive();
}

class Audi extends Car
{
    public function drive()
    {
        //...
    }
}

abstract class Aircraft extends Vehicle
{
    abstract public function drive();
}

class Airbus extends Aircraft
{
    public function drive()
    {
        // ...
    }
}

按照你的例子的字面性质,想想飞机工厂和汽车厂有多大的不同。当然,它们都是制造车辆的工厂(这就是为什么它们各自的工厂可能会从同一个抽象的-and类中派生出来),但是制造飞机的过程与制造汽车的过程非常不同,因此必须为每个工厂定义特殊的工厂子类。

更具体的是,让我们来关注一下为什么和何时使用工厂。假设你在写一个游戏,玩家可以买到一辆车。在用户选择之前,您如何知道要实例化哪辆车?

一个简单的脚本可能会做这样的事情。

代码语言:javascript
复制
$car = null;

switch ($choice) {
    case 'BMW': {
        $car = new BMW();
    } break;

    case 'Audi': {
        $car = new Audi();
    } break;

    ...
}

$car->drive();

这就是工厂的模式。区别在于,一个实际的工厂类给您带来了这个简单脚本没有的几个好处。

首先,考虑一个复制上述脚本功能的CarFactory类。

代码语言:javascript
复制
class CarFactory
{
    public static function create($car) : Car
    {
        switch ($car)
        {
            case 'BMW': return new BMW();
            case 'Audi': return new Audi();
            // ...
        }
    }
}

$car = CarFactory::create($choice);
$car->drive();

一开始,您就不需要null作为“用户还没有选择一辆车”的前哨值。汽车还不存在,所以汽车变量还不存在。

第二,脚本不能从任何东西继承或派生;它只是。相反,如果您希望您的播放器也能够购买Aircraft,或者从Vehicle类派生的任何类型的传输,您可以定义一个基类VehicleFactory类,您可以从中实现您的CarFactoryAircraftFactory类。

代码语言:javascript
复制
interface Build
{
    public static function build($choice);
}

abstract class VehicleFactory implements Build
{
    abstract public static function build($choice) : Vehicle;
}

class AircraftFactory extends VehicleFactory
{
    public static function build($aircraft) : Aircraft
    {
        switch ($aircraft)
        {
            case 'Airbus': return new Airbus();
            case 'Boeing': return new Boeing();
            // ...
        }
    }
}

class CarFactory extends VehicleFactory
{
    public static function build($car) : Car
    {
        switch ($car)
        {
            case 'BMW': return new BMW();
            case 'Audi': return new Audi();
            // ...
        }
    }
}

$aircraft = AircraftFactory::build($choice);
$aircraft->drive();

$car = CarFactory::build($choice);
$car->drive();

希望这能让您了解工厂模式为什么有用。其结果是,基类定义了用户请求创建对象的接口,而工厂子类负责处理实际的定义。此外,根据基本对象定义每个工厂的返回类型(即,CarFactory返回一个Car)允许我们选择实际在运行时创建的对象的实际子类(用户可以选择BMWAudi,它们都是Cars,都是Vehicles,所有这些都是Drivable)。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/250480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档