打破封闭原则的工厂

时间:2011-06-18 18:04:21

标签: design-patterns

Abstract Factory / Factory方法的经典实现基于多态性。但在最低级别,我们必须有一些不基于多态性的工厂,并打破开放原则:

public Device Create(string deviceName)
{
  switch (deviceName)
  {
    case "Device1": return new Device1();
    case "Device2": return new Device2()'
    default: throw new NotSupportedDeviceException(deviceName);
  }
}

这类工厂有什么特别名称吗?

5 个答案:

答案 0 :(得分:7)

从我所看到的,您已经发布了一个完美有效的工厂方法模式示例:

  • Device1和Device2都继承/实现Device类/接口 - 多态仍然是此示例的一个关键方面。
  • 您正在使用Factory Method来封装逻辑,以确定要实例化和返回的具体类。
  • 工厂方法的调用者仍然对所涉及的具体类别一无所知 - 他只知道他找回了一个设备。这正是您希望工厂方法为您做的。

确实,内部实现有点严厉(switch-case)。但是,这并不会使它成为真正的工厂方法模式。

我真的不知道你的例子“不是基于多态”,也不是“打破开放/封闭原则”。如果我完全错过了这一点,请随时更新您的帖子,以帮助我们解决您的问题。

现在,如果Factory方法正在使用传递的deviceName,并使用它来查找要实例化的具体类的完全匹配(使用反射),那将绝对打破Factory Method模式,因为调用者必须具有亲密性了解不同的具体课程。但正如目前所写,传递的deviceName只是决策过程中使用的一段数据 - 它不会破坏工厂模式的封装。

答案 1 :(得分:6)

public class Factory
{
   private Map<String, Device> devices;

    public Factory(Map<String, Device> devices)
    {
        this.devices = devices;
    }

    public Device Create(String deviceName)
    {
         return devices.get(deviceName);
    }
}

使用依赖注入配置地图。

答案 2 :(得分:3)

你在谈论AbstractFactory Factory,对吗?避免你所谈论的一种方法是通过配置。如果根据某些参数或设置选择了正确的工厂,那么您不一定会遇到此问题。例如,部署软件的每个设备都会指定要使用的其他具体实例。这可以手动完成或通过依赖注入完成。如果确实需要做运行时决定,那么我不确定你还能做什么。

答案 3 :(得分:2)

如果要通过允许工厂可扩展来尊重函数中的open-closed principle,则可以使用依赖项注入模式将工厂配置为shown in the answer by brahmagupta

要回答关于您所展示的模式是否有特殊名称的具体问题,答案是否定的。它仍被视为factory method pattern的一个例子。

答案 4 :(得分:0)

这确实是一个工厂方法,使用具体类没有任何问题,因为它们的构造逻辑可能会有所不同,而且这就是Factory可能有用的地方。

但在这种特殊情况下,您可以使用反射或IoC容器来实现低耦合。

例如,如果您正在使用C#和Common Service Locator抽象,那么您可以使用名称注册您的设备实现,然后您根本不需要工厂,因为它看起来像:

public Device Create(string deviceName)
{
    return ServiceLocator.Current.GetInstance<Device>(deviceName);
}