首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单工厂法与工厂化设计模式差异

简单工厂法与工厂化设计模式差异
EN

Stack Overflow用户
提问于 2017-09-30 08:53:02
回答 2查看 2K关注 0票数 6

我正在学习新的设计模式&我试图理解简单工厂和工厂方法模式之间的区别。首先,我想澄清一下,我试着阅读了大量来自Stack溢出和其他网站的文章,但这并没有帮助我。

下面是我的问题:让我们考虑一下我有一个产品层次结构,如下所示:

我编写了一个简单的Factory类,如下所示

代码语言:javascript
复制
public class SimpleItemFactory {

    static Item getItem(String type) {
        if(type.equals("Cake")) {
            return new Cake();
        }else if(type.equals("Chocolate")) {
            return new Chocolate();
        }else {
            return null;
        }
    }
}

所以现在我把所有的对象创建都放在一个地方,所以如果明天有任何更改,occursLike构造函数需要一个参数,我们只需要在一个地方更改。但是它打破了打开、关闭的原则,就好像明天我们添加了更多的项一样,如果条件的话,我们需要更改getItem()方法。所以我们采用工厂方法模式

我们创建工厂类,如下所示:

代码语言:javascript
复制
public abstract class ItemFactory {
    abstract Item getItem();
}

class CakeFactory extends ItemFactory {
    @Override
    Item getItem() {
        return new Cake();
    }
}

class ChocolateFactory extends ItemFactory {
    @Override
    Item getItem() {
        return new Chocolate();
    }
}


class Client{
    public static void main(String[] args) {

        Item chocolate = new ChocolateFactory().getItem();
        System.out.println(chocolate);
    }
 }

现在,当客户机想要添加名为IceCream的新项时,他们只需创建名为IceCreamFactory的新工厂,并根据该工厂创建IceCream,如下所示:

代码语言:javascript
复制
class IceCreamFactory extends ItemFactory{

    @Override
    Item getItem() {
        return new IceCream();
    }

}

class Client{
    public static void main(String[] args) {
        Item iceCream = new IceCreamFactory().getItem();
        System.out.println(iceCream);

    }
}

我的理解是正确的吗?我们在这里满足了开放封闭原则,但是对于每个产品(项目),我们需要一个工厂类,它不是变成了可管理的噩梦吗?

注:文章I指的是https://www.codeproject.com/Articles/1135918/Factory-Patterns-Factory-Method-Pattern?msg=5380215#xx5380215xx

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-30 09:48:11

您的理解实际上是正确的,您需要注意的是,每个设计模式都是为了解决至少一个问题,有时它会带来一些其他的复杂性副作用,这意味着没有完美的设计模式可以解决所有问题。

为了学习的目的,你一个一个地应用设计模式(这使得设计模式的真正力量变得害羞或隐藏),然而在现实世界中,设计模式被混合在一起(甚至你可以发明一个新的设计模式:p),目的是为了创造一些最能满足你的需求并变得接近理想的东西,例如,你可以遇到生成器模式与工厂模式混合或工厂模式与战略模式,甚至三个模式混合在一起.

例如,对于这里的情况,我建议使用工厂方法模式简单工厂模式以及依赖注入模式来创建完全漂亮的东西,同时满足开放封闭原则。

代码语言:javascript
复制
class ItemFactoryContainer() {

    private Map<String, ItemFactory> factories = new HashMap<>();

    public void register(String name, ItemFactory factory) {
        factories.put(name, factory);
    }

    public ItemFactory getFactory(String name) {
        return factories.get(name);
    }
}

public class ItemFactoryTest {

    public static void main(String...args) {

        ItemFactoryContainer factoryContainer = new ItemFactoryContainer();

        factoryContainer.register("choclate", new ChocolateFactory ());
        factoryContainer.register("cake", new CakeFactory ());
        factoryContainer.register("iceCream", new IceCreamFactory  ());

        Chocolate choclate = factoryContainer.getFactory("choclate").getItem();
        Cake cake = factoryContainer.getFactory("cake").getItem();
    }
}
票数 5
EN

Stack Overflow用户

发布于 2017-09-30 09:25:08

我认为在您的例子中,工厂似乎是无用的,因为您的蛋糕和巧克力建设者不需要任何args。

当您想要构造一个包含多个args的复杂对象以尊重DIP (依赖反转原理)并避免尴尬的耦合时,工厂是非常有用的。

此外,您的示例似乎违反了LSP (Liskov替换原则)。蛋糕类和巧克力类没有什么共同点,作为证据,抽象的超类被命名为Item,这是一个非常通用的名称。

对我来说,对于复杂的不常见的对象,按类选择一个工厂更好,并且有效地尊重OCP (开放关闭原则)。

第一个示例可以用于实例化继承相同超类的类,但可以使用类作为arg和反射(使用java.lang.reflect)调用构造函数,而不仅仅是使用字符串计算。(您的IDE无法自动完成该操作),如果没有匹配,则不返回null,抛出一个IllegalArgumentException,则更正确。

就像这样:

代码语言:javascript
复制
import java.lang.reflect.Constructor;

public class SimpleItemFactory {
    public <T extends Item> T createItem(Class<? extends Item> itemClass) {
        try {
            // construct your dependencies here
            // and inject them in the getConstructor
            Constructor<? extends Item> constructor = itemClass.getConstructor();
            return (T)constructor.newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException();
        }
    }
}

像这样使用它:

代码语言:javascript
复制
class Client {
    public static void main(String[] args) {
        SimpleItemFactory factory = new SimpleItemFactory();
        IceCream iceCream = factory.createItem(IceCream.class);
        System.out.println(iceCream);
        Cake cake = factory.createItem(Cake.class);
        System.out.println(cake);
        Chocolate chocolate = factory.createItem(Chocolate.class);
        System.out.println(chocolate);
    }
}

如果没有依赖项,则可以在抽象项类中将createItem()方法直接实现为静态方法。

看这本书,这是一个很好的资源:头第一设计模式

OCP只是开放的扩展,封闭的修改原则。如果您需要打开以修改您的工厂以添加一个新的类(一个在开关中管理的新案例或一个if),则不是,您的工厂不是"OCP“。

你不应该在构造函数中计算税收,构造函数应该只是.构造一个对象。您可以使用类似于策略的模式来拥有许多taxesCalculator,并将它们注入构造函数中,使用IOC (反转控制)机制,比如依赖项注入,或者以简单的方式使用工厂(它是可以接受的),但不能使用类中的简单静态方法。

对不起,我的英语很差,我很难回答这样一个复杂的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46501200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档