6

我知道工厂方法相对于简单工厂的主要优势之一是它不违反开闭 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 帖子,但没有一个解决这个特定的区别。

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

4

1 回答 1

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 设计模式内存/抽象工厂。

VARIANT 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 语句,并且不会在客户端或工厂端违反打开/关闭原则。

于 2015-02-18T11:47:35.570 回答