通过工厂方法将参数传递给特定的子类

发布于 2024-07-19 09:13:58 字数 398 浏览 4 评论 0原文

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

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

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

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

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

Let's say I have an abstract class Drink, and a factory method which chooses the type of Drink (Wine, Beer, etc.) to create at runtime.

Each Drink needs some arguments to properly initialize itself. Some of these are common to all Drinks; for example, they might all require a DrinkConfig argument.

But each Drink may have its own unique requirements too. Maybe Wine needs a Sommelier helper object to initialize itself. Beer doesn't need that, but it may need its own helper objects.

So what should I pass to the factory method? When I call it, I have all the helper objects available, so I could just pass all of them to the factory. But this could end up being a lot of arguments. Is there a better way to design this?

EDIT: Let's assume I can't just create the helper objects in the factory; they're only available from the caller.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

维持三分热 2024-07-26 09:13:58

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

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);
    }
}

编辑:

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

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.");
        }
    }
}

I'd create different overload methods in your factory class.

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);
    }
}

Edit:

If it's desired to to only have a single method in the Factory class an alternative implementation would be:

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.");
        }
    }
}
我乃一代侩神 2024-07-26 09:13:58

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

The factory method should abstract away the details of how to create values. So you should not be passing helper objects to the factory method, the factory method should be creating the helper object it needs and passing that to the appropriate constructor.

别想她 2024-07-26 09:13:58

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

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

A Factory should be creating very similar objects in the first place. This means that even though all of these objects are drinks, the factory method may not be appropriate because each drink is simply much different from another.

With that being said, you could instead pass a List of Objects of size equal to the number of properties you want to set. Each object would then represent the value you want to set in the constructor of the appropriate object, in the order in which you want to set these variables. The downside to this is that you have to format a List outside of the factory before making the call, which is somewhat clumsy.

不顾 2024-07-26 09:13:58

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

显然,你可能会想再建一家工厂来生产原料——但这会导致先有鸡还是先有蛋的问题。

I am tempted to provide a naive solution where your ingredients are derived from a base class 'DrinkIngredients'. You will have to match the sub-class to be used for a particular drink.

Apparently, you may be tempted to create another factory for the ingredients -- but that would lead to a chicken-and-egg problem.

苄①跕圉湢 2024-07-26 09:13:58

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

此外,在许多情况下,诸如 Spring 之类的框架将用于允许您在配置文件而不是代码中描述这些关系。

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

Generally, a factory method exists to hide these details. One important question is where the Sommelier comes from -- if all of these other helpers are singleton or can be acquired from a known source, then instantiate the factory the necessary information to go and find them, so that your calling code doesn't need to worry about it.

Also, in many cases, a framework such as Spring would be used to allow you to describe these relationships in a configuration file rather than in code.

If you really need to pass the helpers in at runtime from the calling code, I suggest reading the paper 'Arguments and Results' (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.7565) which describes a common pattern for marshalling complex arguments. Essentially, you would create an intermediate collection of the necessary parameters and pass that to the factory.

吲‖鸣 2024-07-26 09:13:58

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

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

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

In cases like this, I usually look towards other solutions instead of passing in variables.

For example, in your case - WineFactory needing a Sommelier, so it can construct the appropriate Wine -

This is a great use case for runtime dependency injection. A dependency injection framework of some form would make this very simple, understandable, and just kind of work without needing to have all of these properties passed around.

弥繁 2024-07-26 09:13:58

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

This looks like a perfect case for the Builder pattern. Use the Factory pattern for creating similar objects, and the Builder pattern for constructing complex, dissimilar objects. Trying to use the Factory pattern for this problem will lead to many, dissimilar initialization constructors(with different numbers/types of parameters) for the different objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文