Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 通过工厂方法将参数传递给特定的子类_Oop_Subclass_Factory - Fatal编程技术网

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

Oop 通过工厂方法将参数传递给特定的子类,oop,subclass,factory,Oop,Subclass,Factory,假设我有一个抽象类dike,还有一个工厂方法,它选择在运行时创建的饮料类型(葡萄酒、啤酒等) 每种饮料都需要一些参数来正确初始化自身。其中一些是所有饮料中常见的;例如,它们可能都需要一个DrinkConfig参数 但每种饮料也可能有其独特的要求。也许Wine需要一个侍酒师助手对象来初始化自己。啤酒不需要它,但它可能需要自己的助手对象 那么我应该把什么传递给工厂方法呢?当我调用它时,我有所有的helper对象可用,所以我可以将它们全部传递给工厂。但这最终可能会引起很多争论。有更好的设计方法吗 编辑

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

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

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

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


编辑:假设我不能在工厂中创建辅助对象;它们只能从调用方获得。

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

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

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


显然,你可能会想为这些成分创建另一个工厂,但这会导致鸡和蛋的问题。

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

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


如果您真的需要在运行时从调用代码中传递helpers,我建议您阅读“Arguments and Results”(参数和结果)一文,该文描述了编组复杂参数的常见模式。本质上,您将创建一个必要参数的中间集合,并将其传递给工厂。

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

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

例如,在您的案例中,酒厂需要一名侍酒师,因此它可以制造合适的葡萄酒-


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

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


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

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

签名很好。问题是如何将参数传递给Factory::CreateDrink()(或调用它的任何对象)。如果希望在工厂中拥有CreateDrink方法,可以使用枚举参数指定所需的饮料类型。我不相信上述方法符合GoF工厂模式,即对象是在饮料类中创建的(今晚我需要查看我的书),但是我发现它更加实用,并且它仍然保持了为子类层次结构集中对象创建的主要好处。在检查了我的GoF设计模式书之后,我很高兴我上面提供的示例与如何将工厂作为抽象工厂设计模式的一部分非常接近。为了完全符合规范,应该有一个DrinkFactory继承自的抽象工厂类,但对于像这样的简单情况,我通常不考虑它。如果需要另一个具体的工厂,重构DrinkFactory就足够容易了。不幸的是,这对我的案例来说并不奏效。具体类型是在运行时选择的,因此我不能选择调用特定的CreateBeer或CreateWine方法。我只是调用了一个通用的CreateDrink方法,它返回啤酒或葡萄酒。不幸的是,您的编辑示例并没有回答他的问题:如何处理不同的签名?