【问题标题】:Simple Factory vs Factory Method: Switch statement in factory vs. client简单工厂与工厂方法:工厂与客户端中的 Switch 语句
【发布时间】:2015-02-17 17:52:57
【问题描述】:

我知道,与简单工厂相比,工厂方法的主要优势之一是它不违反开闭 SOLID 原则。即前者在添加新类型时不需要修改switch语句。

有一件我希望得到澄清。如果我要使用一个简单的工厂,我会有一个这样的工厂(简化):

public class ObjectFactory {
    public static IObject CreateObject(ObjectTypeEnum objectType) {
        switch (objectType) {
            case TypeA:
                return ObjectA;
                break;
            case TypeB:
                return ObjectB;
                break;
            case TypeC:
                return ObjectC;
                break;
        }
    }
}

客户会这样称呼它:

IObject myObject = ObjectFactory.CreateObject(objectType);

文献中的缺点是添加新对象类型时需要修改 CreateObject。

但是使用工厂方法,我们不只是将这个修改从工厂转移到客户端,就像这样(客户端代码):

IObject myObject;
switch (objectType) {
            case TypeA:
                myObject = ObjectAFactory.CreateObject();
                break;
            case TypeB:
                myObject = ObjectBFactory.CreateObject();
                break;
            case TypeC:
                myObject = ObjectCFactory.CreateObject();
                break;
}

在这种情况下,每次添加新类型时都需要修改客户端,而在前一种情况下,需要修改工厂。那么,一个比另一个有什么优势呢?请不要将其标记为重复,我查看了许多关于工厂的 SO 帖子,但没有一个解决这个特定的区别。

有没有更好的解决方案,在客户端或工厂端都不会违反开放/封闭原则?

【问题讨论】:

标签: design-patterns factory factory-pattern solid-principles open-closed-principle


【解决方案1】:

标准的Abstract Factory 设计模式没有帮助?
简化的 Java 代码:

public interface IFactory {
    IObject createObject();
}

public class FactoryA implements IFactory {
    public IObject createObject() {
        return new ObjectA();
    }
}

public class FactoryB implements IFactory {
    public IObject createObject() {
        return new ObjectB();
    }
}

Client is configured (injected) with the needed Factory at run-time
    IFactory myFactory = ...   // new FactoryA();
...
IObject  myObject = myFactory.createObject();
...

另请参阅 http://w3sdesign.com 上的 GoF 设计模式内存/抽象工厂。

变体 2
不要使用枚举对象类型,而是使用多态定义您的对象类型(以避免使用 switch 语句)。 简化的 Java 代码:

public interface IObjectType {
    int getObjectType();
    IObject createObject();
}

public class ObjectTypeA implements IObjectType {
    ...
    public IObject createObject() {
        return new ObjectA();
    }
}

public class ObjectTypeB implements IObjectType {
    ...
    public IObject createObject() {
        return new ObjectB();
    }
}

Client determines object type 
IObjectType myObjectType = ...   // new ObjectTypeA();
...
IObject  myObject = myObjectType.createObject();
...

我的结论:
我认为,更好的解决方案是使用多态性而不是使用枚举常量来设计您的类型。 这将避免 switch 语句,并且不会在客户端或工厂端违反打开/关闭原则。

【讨论】:

  • 这本质上是我上面第二个选项的变体。这对我不起作用的原因是,就我而言,工厂的“客户端”实际上是一个 Web API。 Web API 的客户端(“客户端的客户端”)将是对象类型的决定因素,所以我看不到在不切换对象类型的情况下注入它的方法,无论是在创建IFactory 或工厂本身。
  • 客户端如何判断对象类型?
  • 客户端将他们想要的对象类型传递给api。对象类型是一个枚举值。
  • 我的意思是,比如是对象类型TypeA = InterfaceA / ClassA / typeOf ObjectA之类的。
  • objectType 是一个枚举值。
猜你喜欢
  • 1970-01-01
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
相关资源
最近更新 更多