微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有对象可替换性的工厂设计模式?

如何解决具有对象可替换性的工厂设计模式?

有很多关于 factory 模式的文章,但我认为它在本质上失败了。示例:

final class Car
{
    public function carMethod() { echo __CLASS__.'.'.__FUNCTION__.'<br>'; }
}

final class Vehicle
{
    public function vehicleMethod() { echo __CLASS__.'.'.__FUNCTION__.'<br>'; }

}

final class Factory
{
    public function createNewCar() : Car
    {
        return new Car();
    }

    public function createNewVehicle() : Vehicle
    {
        return new Vehicle();
    }
}

到目前为止一切顺利。现在我想让它可配置,因为在这一点上,类仍然与它耦合:

final class Factory
{
    private array $map;

    public function __construct(array $map)
    {
        $this->map = $map;
    }

    public function createNewCar() : Car
    {
        return new $this->map['carClass'];
    }

    public function createNewVehicle() : Vehicle
    {
        return new $this->map['vehicleClass'];
    }
}

$factory = new Factory(
    'carClass' => 'Car'
    'vehicleClass' => 'Vehicle'
]);
$factory->createNewCar();

现在工厂是可配置的。但不幸的是,类仍然是由语言本身耦合的!当然,我总是可以在 createNew.... 方法的末尾省略类,但是如果它是一种类型化语言呢?如何完全替换对象?如果我尝试这样做会怎样:

final class Car2 {}

final class Vehicle2 {}

$factory = new Factory(
    'carClass' => 'Car2'
    'vehicleClass' => 'Vehicle2'
]);
$factory->createNewCar();

它会抛出一个致命错误Car2 不是 Car。即使使用继承,也不总是有可能(注意 final 关键字)。我无法替换对象!

编辑:当然可以用接口解决

interface ICar
{
    public function carMethod();
}
final class Car implements ICar
{
    public function carMethod() { echo __CLASS__.'.'.__FUNCTION__.'<br>'; }
}
final class Car2 implements ICar
{
    public function carMethod() { echo __CLASS__.'.'.__FUNCTION__.'<br>'; }
}

interface IVehicle
{
    public function vehicleMethod();
}
final class Vehicle implements IVehicle
{
    public function vehicleMethod() { echo __CLASS__.'.'.__FUNCTION__.'<br>'; }
}
final class Vehicle2 implements IVehicle
{
    public function vehicleMethod() { echo __CLASS__.'.'.__FUNCTION__.'<br>'; }
}

final class Factory
{
    public function createNewCar() : ICar
    {
        return new Car();
    }

    public function createNewVehicle() : IVehicle
    {
        return new Vehicle();
    }
}

但是创建/更新这些接口并添加“实现”关键字很乏味......

解决方法

你想做什么?工厂模式的目标是将对象的构造与其使用分离。这个想法是您将以相同的方式使用多个对象,而不考虑实际的实现。你的例子不是很好,在那种情况下,你是对的,使用工厂模式没有任何意义。

让我们假设 Car 继承自 Vehicle,而 Plane 也继承自 Vehicle,这是一个有方法 move(distance) 的接口。两者都有一个以 int move(distance) 作为签名的方法。 int 是行驶给定距离的分钟数。

事实证明,在您的系统中,选择乘坐汽车还是飞机取决于您在启动系统时花费的资金。如果您花费超过 1000 欧元,那么您将拥有飞机作为交通工具,否则您将拥有汽车。作为用户,您将使用车辆的移动功能旅行,因此描述您的旅行的所有逻辑不应依赖于车辆接口的实现。此外,由于未来车辆的价格可能会有所不同(例如,下次运行时为 1200 欧元),您不希望 User 类知道价格市场是如何计算的。您想要做的就是在市场上扔掉您的钱,并获得您可以获得的最好的车辆。在这种情况下,我们将应用工厂模式,工厂可能会被称为 VehicleMarket 之类的东西。

UML diagram representing the implementation chosen for this system

在这个例子中,用户不需要知道他有汽车还是飞机,从这些类中解耦。但是,用户仍然耦合在 VehicleMarket 和 Vehicle 上。这是完全有道理的,因为如果 VehicleMarket 的功能发生变化,那么用户很有可能也需要改变它与此类交互的方式。车辆也是一样,如果移动函数给出的合约发生变化,那么用户可能不得不以不同的方式使用车辆。

目标不是将系统的每个部分彼此分离。目标是在模块之间设置正确的边界,以便在必须实现新功能时不必更改整个系统。这就是一致性的含义。例如,如果必须扩展之前的系统以添加新车辆(例如卡车),则只需更改 VehicleMarket。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。