工厂模式和抽象工厂模式之间的基本区别是什么?


当前回答

很多人可能会感到惊讶,但这个问题是不正确的。如果你在面试中听到这个问题,你需要帮助面试官理解你的困惑在哪里。

让我们从一个事实开始,即没有具体的模式被称为“工厂”。有一种模式叫做“抽象工厂”,也有一种模式叫做“工厂方法”。

那么,“工厂”是什么意思呢?以下之一(根据引用的范围,都可以认为是正确的):

有些人用它作为“抽象工厂”的别名(快捷方式)。 有些人使用它作为“工厂方法”的别名(快捷方式)。 有些人将其用作所有工厂/创建模式的通用名称。例如,“抽象工厂”和“工厂方法”都是工厂。

不幸的是,许多人使用“Factory”来表示另一种类型的工厂,它创建了一个或多个工厂(或它们的接口)。根据他们的理论:

Product实现了IProduct,它是由Factory创建的 实现了由AbstractFactory创建的IFactory。

为了理解这有多愚蠢,让我们继续我们的方程:

AbstractFactory实现了IAbstractFactory,它由… AbstractAbstractFactory ? ?

我希望你能明白我的意思。不要困惑,请不要发明那些无缘无故存在的东西。

-

附注:产品的工厂是AbstractFactory,而抽象工厂的工厂也是AbstractFactory的另一个例子。

其他回答

工厂方法和抽象工厂都使客户端与具体类型解耦。两者都创建对象,但是工厂方法使用继承,而抽象工厂方法使用组合。

工厂方法在子类中继承,用于创建具体的对象(产品),而抽象工厂提供了用于创建相关产品族的接口,这些接口的子类定义了如何创建相关产品。

然后这些子类在实例化后被传递到产品类中,在产品类中它被用作抽象类型。抽象工厂中的相关产品通常使用工厂方法来实现。

这些工厂的主要区别是什么时候你想用工厂做什么,什么时候你想使用它。

有时候,当你在做IOC(控制反转,例如构造函数注入)时,你知道你可以创建固体对象。如上面的水果示例所述,如果准备创建水果对象,可以使用简单的工厂模式。

但是很多时候,你不想创建实体对象,它们会在程序流的后面出现。但是配置告诉你你想在开始时使用什么样的工厂,而不是创建对象,你可以将从公共工厂类派生的工厂传递给IOC中的构造函数。

所以,我认为这也是关于对象的生命周期和创建。

使用Factory模式,您可以生成特定接口(例如,IFruit)的实现实例(Apple、Banana、Cherry等)。

使用抽象工厂模式,您可以为任何人提供他们自己的工厂提供一种方法。这使得您的仓库可以是IFruitFactory或IJuiceFactory,而不需要您的仓库了解任何关于水果或果汁的信息。

我认为我们可以通过查看Java8示例代码来理解这两者之间的区别:

  interface Something{}

  interface OneWhoCanProvideSomething {
     Something getSomething();
  }

  interface OneWhoCanProvideCreatorsOfSomething{
     OneWhoCanProvideSomething getCreator();
  }


public class AbstractFactoryExample {

    public static void main(String[] args) {
        //I need something
        //Let's create one
        Something something = new Something() {};

        //Or ask someone (FACTORY pattern)
        OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeA = () -> null;
        OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeB = () -> null;

        //Or ask someone who knows soemone who can create something (ABSTRACT FACTORY pattern)
        OneWhoCanProvideCreatorsOfSomething oneWhoCanProvideCreatorsOfSomething = () -> null;

        //Same thing, but you don't need to write you own interfaces
        Supplier<Something> supplierOfSomething = () -> null;
        Supplier<Supplier<Something>> supplierOfSupplier = () -> null;
    }

}

现在的问题是你应该使用哪种创造方式以及为什么: 第一种方式(没有模式,只是普通的构造函数):自己创建不是一个好主意,你必须做所有的工作,你的客户端代码绑定到特定的实现。

第二种方式(使用Factory模式):为您提供了可以传递任何类型的实现的好处,这些实现可以基于某些条件(可能是传递给创建方法的参数)提供不同类型的东西。

第三种方法(使用抽象工厂模式):这为您提供了更多的灵活性。您可以根据某些条件(可能是传递的参数)找到不同类型的创建者。

请注意,您总是可以通过将两个条件组合在一起来摆脱工厂模式(这稍微增加了代码的复杂性和耦合),我想这就是为什么我们很少看到抽象工厂模式的实际用例。

延伸John Feminella的回答:

Apple, Banana, Cherry实现了FruitFactory,它有一个叫做Create的方法,它只负责创建Apple, Banana或Cherry。Factory方法就完成了。

现在,你想用你的水果创建一个特殊的沙拉,这就是你的抽象工厂。抽象工厂知道如何用苹果、香蕉和樱桃制作你的特殊沙拉。

public class Apple implements Fruit, FruitFactory {
    public Fruit Create() {
        // Apple creation logic goes here
    }
}

public class Banana implements Fruit, FruitFactory {
    public Fruit Create() {
        // Banana creation logic goes here
    }
}

public class Cherry implements Fruit, FruitFactory {
    public Fruit Create() {
        // Cherry creation logic goes here
    }
}

public class SpecialSalad implements Salad, SaladFactory {
    public static Salad Create(FruitFactory[] fruits) {
        // loop through the factory and create the fruits.
        // then you're ready to cut and slice your fruits 
        // to create your special salad.
    }
}