Design patterns 打破开闭原则的工厂

Design patterns 打破开闭原则的工厂,design-patterns,Design Patterns,抽象工厂/工厂方法的经典实现是基于多态性的。但在最低层次上,我们必须有某种工厂,它不是基于多态性和打破开放-关闭原则: public Device Create(string deviceName) { switch (deviceName) { case "Device1": return new Device1(); case "Device2": return new Device2()' default: throw new NotSupportedDev

抽象工厂/工厂方法的经典实现是基于多态性的。但在最低层次上,我们必须有某种工厂,它不是基于多态性和打破开放-关闭原则:

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

这种工厂有什么特别的名字吗?

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

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

从我看到的情况来看,您发布了一个非常有效的Factory方法模式示例:

  • Device1和Device2都继承/实现设备类/接口-多态性仍然是本示例的一个关键方面
  • 您正在使用工厂方法来封装逻辑,以确定实例化和返回哪个具体类
  • 工厂方法的调用方仍然很好地不知道所涉及的具体类——他只知道自己得到了一个设备。这正是您希望工厂方法为您所做的
的确,内部实现有点笨手笨脚(switch case)。然而,这并没有使它成为真正的工厂方法模式

我真的不知道你的例子在哪里“不是基于多态性”,也不知道它在哪里“打破了开放/封闭原则”。如果我完全没有抓住要点,请随时更新您的帖子,以帮助我们关注您的问题


现在,如果工厂方法使用传递的deviceName,并使用它来找到要实例化的具体类的精确匹配(使用反射),这将完全打破工厂方法模式,因为调用方必须熟悉不同的具体类。但正如目前所写,传递的deviceName只是决策过程中使用的一段数据——它不会破坏工厂模式的封装。

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

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);
    }
}
  • Device1和Device2都继承/实现设备类/接口-多态性仍然是本示例的一个关键方面
  • 您正在使用工厂方法来封装逻辑,以确定实例化和返回哪个具体类
  • 工厂方法的调用方仍然很好地不知道所涉及的具体类——他只知道自己得到了一个设备。这正是您希望工厂方法为您所做的
的确,内部实现有点笨手笨脚(switch case)。然而,这并没有使它成为真正的工厂方法模式

我真的不知道你的例子在哪里“不是基于多态性”,也不知道它在哪里“打破了开放/封闭原则”。如果我完全没有抓住要点,请随时更新您的帖子,以帮助我们关注您的问题

现在,如果工厂方法使用传递的deviceName,并使用它来找到要实例化的具体类的精确匹配(使用反射),这将完全打破工厂方法模式,因为调用方必须熟悉不同的具体类。但正如目前编写的,传递的deviceName只是决策过程中使用的一段数据——它不会破坏工厂模式的封装。

公共类工厂
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);
    }
}
{ 专用地图设备; 公共工厂(地图设备) { 这个。设备=设备; } 公共设备创建(字符串deviceName) { 返回设备.get(deviceName); } }
使用依赖项注入配置映射。

公共类工厂
{
专用地图设备;
公共工厂(地图设备)
{
这个。设备=设备;
}
公共设备创建(字符串deviceName)
{
返回设备.get(deviceName);
}
}

使用依赖项注入来配置映射。

这确实是一种工厂方法,使用具体类没有什么错,因为它们的构造逻辑可能会有所不同,而这正是工厂有用的地方

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

例如,如果您正在使用C#和公共服务定位器抽象,那么您可以用名称注册设备实现,这样您甚至不需要工厂,因为它看起来像:

public Device Create(string deviceName)
{
    return ServiceLocator.Current.GetInstance<Device>(deviceName);
}
公共设备创建(字符串deviceName)
{
返回ServiceLocator.Current.GetInstance(deviceName);
}

这确实是一种工厂方法,使用具体类没有什么错,因为它们的构造逻辑可能会有所不同,而这正是工厂有用的地方

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

例如,如果您正在使用C#和公共服务定位器抽象,那么您可以用名称注册设备实现,这样您甚至不需要工厂,因为它看起来像:

public Device Create(string deviceName)
{
    return ServiceLocator.Current.GetInstance<Device>(deviceName);
}
公共设备创建(字符串deviceName)
{
返回ServiceLocator.Current.GetInstance(deviceName);
}
如果您