此代码是实现 'Factory Pattern'、工厂方法,还是 none?

Is this code implements 'Factory Pattern', factory methods, both or none?

虽然这个话题已经被讨论过很多次了,但我还是觉得自己太糊涂了。

我有这个简单的代码示例:

public class FruitFactory {

    public static Apple getApple() {
        return new Apple();
    }

    public static Banana getBanana() {
        return new Banana();
    }

    public static Orange getOrange() {
        return new Orange();
    }
}

如果我让我的客户接触到一些创建的复杂性,如下例所示,它是糟糕的工厂实现吗?

public static Orange getOrange(String weight, String size,) {
    return new Orange(weight, size);
}

正如所说,工厂只是一种抽象,其中对象创建实现被有意封装在工厂的 public 接口后面。工厂不一定是 class,也不一定是包——不同的语言以不同的方式实现状态和行为细节的封装(例如考虑闭包)。

允许 "top-level" 函数的语言中的函数,也可以是工厂:

public Orange growNewOrange(String weight, String size) {
    /// ...traditionally not callers concern.
}

如果工厂将创建代码隐藏在某种方式后面,供您使用它而不用担心 每个 创建的对象的创建代码,您已经有了一个有用的隔离(在获取新对象和管理它们的对象)解决了工厂模式旨在解决的问题。

有设计用来创建和管理一种对象的工厂,也有用来创建和管理多种对象的工厂。水果工厂,您可以在其中指定具体的 class 您想要的水果,仍然匹配有效的工厂模式。

将工厂实现分类为 "types" 是由各种 OOP 作者完成的,出于各种充分的原因可能很有用,但这对于能够利用一般思想为您带来好处并不是必需的。

立即有用的建议是将创建代码封装在 Java 包或 class 中,其中指定创建对象的参数是在每个对象的基础上完成的,而工厂状态控制创建逻辑——例如重用对象池的大小等——是在工厂创建过程中设置的。对象池是工作中工厂模式的示例之一。

  • 第一个代码是 Factory 模式,因为您只有一个 class 没有子classing、覆盖等

当您想使用工厂方法而不是编写(Banana 继承自 Fruit)时:

public abstract FruitFactory {
    public abstract Fruit createFruit();
}

public BananaFactory extends FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Banana();
    }
}

实施:

public static Orange getOrange(String weight, String size) {
    return new Orange(weight, size);
}

在我看来也是一个正确的实现,因为你封装了创建逻辑,就像@amn 解释的那样。

使用static方法的好处是可以构造构造函数private,因此只能使用该方法实例化对象。

为了更好地理解,请参阅以下内容 link:patterns

工厂模式的目的是在对象创建之上放置一个抽象层。

如果对象有足够的信息可以在没有太多参数或设置的情况下创建自己,那么您不需要使用工厂模式,因为对象的构造函数本身就是一个工厂。

这是您当前代码的问题,它没有向任何内容添加抽象层。您只需封装构造函数。

第二个代码示例的问题是一样的,如果它是一个工厂,那么它会随机或通过算法选择水果的重量或大小,就像一棵真正的树一样。

编辑:原来的四人帮描述是

"Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses."

这意味着,您的代码不是工厂,因为您需要定义所需内容。