8

假设我有一个抽象类 Drink 和一个工厂方法,它选择在运行时创建的饮料类型(葡萄酒、啤酒等)。

每个 Drink 都需要一些参数来正确初始化自己。其中一些是所有饮料共有的;例如,它们可能都需要 DrinkConfig 参数。

但每种饮料也可能有其独特的要求。也许 Wine 需要一个侍酒师辅助对象来初始化自己。Beer 不需要它,但它可能需要它自己的辅助对象。

那么我应该将什么传递给工厂方法?当我调用它时,我拥有所有可用的辅助对象,所以我可以将它们全部传递给工厂。但这最终可能会引发很多争论。有没有更好的方法来设计这个?

编辑:假设我不能只在工厂中创建辅助对象;它们只能从呼叫者那里获得。

4

7 回答 7

4

我会在你的工厂类中创建不同的重载方法。

public class DrinkFactory {

    public static Drink CreateBeer(DrinkConfig config, string hops) {
        return new Beer(config, hops);
    }

    public static Drink CreateWine(DrinkConfig config, string grapes, int temperature) {
        return new Wine(config, grapes, temperature);
    }
}

编辑:

如果希望在 Factory 类中只有一个方法,则替代实现将是:

public enum DrinksEnum {
    Beer,
    Wine
}

public class DrinkFactory {

    public static Drink CreateDrink(DrinksEnum drinkType, DrinkConfig config) {
        switch(drinkType) {
            case DrinksEnum.Beer:
                return new Beer(config);
            case DrinksEnum.Wine:
                return new Wine(config);
            default:
                throw new ApplicationException("Drink type not recognised.");
        }
    }
}
于 2009-05-13T01:01:02.977 回答
2

工厂方法应该抽象出如何创建值的细节。所以你不应该将辅助对象传递给工厂方法,工厂方法应该创建它需要的辅助对象并将其传递给适当的构造函数。

于 2009-05-13T01:04:57.617 回答
1

工厂应该首先创建非常相似的对象。这意味着即使所有这些对象都是饮料,工厂方法也可能不合适,因为每种饮料都与另一种完全不同。

话虽如此,您可以改为传递大小等于您要设置的属性数量的对象列表。然后,每个对象将代表您要在相应对象的构造函数中设置的值,按照您要设置这些变量的顺序。这样做的缺点是你必须在调用之前在工厂之外格式化一个列表,这有点笨拙。

于 2009-05-13T01:12:05.163 回答
0

我很想提供一个简单的解决方案,其中您的成分来自基类“DrinkIngredients”。您必须匹配要用于特定饮料的子类。

显然,您可能很想为原料创建另一个工厂——但这会导致先有鸡还是先有蛋的问题。

于 2009-05-13T01:03:17.667 回答
0

通常,存在工厂方法来隐藏这些细节。一个重要的问题是侍酒师来自哪里——如果所有这些其他助手都是单例的或者可以从已知来源获得,那么实例化工厂所需的信息以找到它们,这样您的调用代码就不需要担心它。

此外,在许多情况下,将使用 Spring 等框架来允许您在配置文件中而不是在代码中描述这些关系。

如果您确实需要在运行时从调用代码中传递帮助程序,我建议您阅读论文“参数和结果”(http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.7565 ),它描述了编组复杂参数的常见模式。本质上,您将创建必要参数的中间集合并将其传递给工厂。

于 2009-05-13T01:03:40.707 回答
0

在这种情况下,我通常会寻找其他解决方案而不是传递变量。

例如,在您的情况下 - WineFactory 需要侍酒师,因此它可以构建适当的 Wine -

这是运行时依赖注入的一个很好的用例。某种形式的依赖注入框架将使这项工作变得非常简单、易于理解并且只是一种工作,而无需传递所有这些属性。

于 2009-05-13T01:08:57.107 回答
0

这看起来是该Builder模式的完美案例。使用Factory创建相似对象的Builder模式,以及构造复杂、不同对象的模式。尝试Factory对这个问题使用该模式将导致针对不同对象的许多不同的初始化构造函数(具有不同数量/类型的参数)。

于 2014-05-04T19:00:56.927 回答