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);
}
}
这类工厂有什么特别名称吗?
答案 0 :(得分:7)
从我所看到的,您已经发布了一个完美有效的工厂方法模式示例:
确实,内部实现有点严厉(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);
}