工厂和抽象工厂模式之间的基本区别是什么?
工厂和抽象工厂模式之间的基本区别是什么?
使用工厂模式,您可以生成特定界面的实现( Apple
, Banana
, Cherry
等),比如说IFruit
。
使用抽象工厂模式,可以生成特定工厂接口的实现,例如IFruitFactory
。 每个人都知道如何创造不同种类的水果。
来源: http : //java.dzone.com/news/intro-design-patterns-abstract
抽象工厂与工厂方法
抽象工厂的方法被实现为工厂方法。 抽象工厂模式和工厂方法模式都通过抽象types和工厂将客户系统与实际的实现类分离开来。 Factory Method通过inheritance创build对象,抽象工厂通过组合创build对象。
抽象工厂模式由AbstractFactory,ConcreteFactory,AbstractProduct,ConcreteProduct和Client组成。
如何实施
抽象工厂模式可以使用工厂方法模式,原型模式或单例模式来实现。 ConcreteFactory对象可以实现为Singleton,因为只需要ConcreteFactory对象的一个实例。
工厂方法模式是抽象工厂模式的简化版本。 工厂方法模式负责创build属于一个家族的产品,而抽象工厂模式处理多个产品族。
工厂方法使用接口和抽象类来将客户端从生成器类和生成的产品中分离出来。 抽象工厂有一个发电机,它是几个工厂方法的容器,以及将客户端与发电机和产品分离的接口。
何时使用工厂方法模式
当需要将客户端与其使用的特定产品分离时,请使用“工厂方法”模式。 使用工厂方法来减轻客户负责创build和configuration产品实例的责任。
何时使用抽象工厂模式
客户端必须与产品类别分离时,使用抽象工厂模式。 特别适用于程序configuration和修改。 抽象工厂模式也可以强制约束哪些类必须与其他类一起使用。 制造新的混凝土工厂可能是很多工作。
例子:
抽象工厂实例1
这种磁盘在面食制作机中准备不同types的面食的规格是抽象工厂,每个特定的磁盘是工厂。 所有工厂(面食制造商磁盘)从抽象工厂inheritance它们的属性。 每个单独的磁盘包含如何创build意大利面的信息,而意大利面制造商则没有。
抽象工厂实例2:
冲压设备对应于抽象工厂,因为它是创build抽象产品对象的操作的接口。 模具对应于混凝土厂,因为他们创造了一个具体的产品。 每个零件类别(胡德,门等)对应于抽象产品。 具体部件(即99 camry的驾驶员侧门)对应于混凝土制品。
工厂方法示例:
玩具公司对应于造物主,因为它可以使用工厂来创build产品对象。 制造特定types的玩具(马或汽车)的玩具公司的分部对应于ConcreteCreator。
工厂模式:工厂生产IProduct实现
抽象工厂模式:工厂生产IFactories,反过来生产IProducts 🙂
[根据意见更新]
根据维基百科的说法,我之前写的是不正确的。 抽象工厂只是一个工厂界面。 有了它,您可以在运行时切换工厂,以允许在不同的上下文中使用不同的工厂。 例子可能是不同的工厂,不同的操作系统,SQL提供商,中间件驱动程序等。
抽象工厂模式
-
提供一个接口来创build相关或依赖对象的族,而不指定它们的具体类。
-
抽象工厂模式与工厂方法模式非常相似。 两者之间的一个区别是,使用抽象工厂模式,类将委托对象实例化的责任通过组合而另一个对象,而工厂方法模式使用inheritance,并依赖于一个子类来处理所需的对象实例化。
-
实际上,委托对象经常使用工厂方法来执行实例化!
工厂模式
-
工厂模式是创build模式的例子
-
创build模式抽象对象实例化过程。 它们隐藏如何创build对象,并帮助整个系统独立于其对象的创build和组成。
-
类创build模式着重于使用inheritance来决定要实例化的对象Factory Method
-
对象创build模式着重于将实例化的委托给另一个对象抽象工厂
参考: 工厂与抽象工厂
工厂方法:您有一个工厂创build从特定基类派生的对象
抽象工厂:你有一个创build其他工厂的工厂 ,而这些工厂反过来创build从基类派生的对象。 你这样做是因为你经常不想创build一个单独的对象(就像Factory方法一样),而是想创build一个相关对象的集合。
抽象工厂是创build相关对象的接口,但工厂方法是一种方法。 抽象工厂是由工厂方法实施的。
基本区别:
工厂:创build对象而不将实例化逻辑公开给客户端。
工厂方法 :定义创build对象的接口,但让子类决定实例化哪个类。 Factory方法让类将实例化推迟到子类
抽象工厂 :提供一个接口,用于创build相关或依赖对象的族,而不指定具体的类。
AbstractFactory模式使用组合来将创build对象的责任委托给另一个类,而Factory方法模式使用inheritance并依赖于派生类或子类来创build对象
从oodesign文章:
工厂类图:
例如:StaticFactory
public class ShapeFactory { //use getShape method to get object of type shape public static Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
实现FactoryMethod实例的非静态工厂可以在这篇文章中find:
devise模式:工厂vs工厂方法与抽象工厂
何时使用:客户端只需要一个类,并不关心它得到的具体实现。
工厂方法类digaram:
何时使用:客户端不知道在运行时需要创build哪些具体的类,但只想获得一个可以完成这个工作的类。
dzone的 抽象工厂类图
何时使用:当您的系统必须创build多个产品系列,或者您想提供产品库而不公开实施细节。
上述文章中的源代码示例很好地理解了这些概念。
相关SE问题与代码示例:
工厂模式。 何时使用工厂方法?
区别:
- 抽象工厂类通常使用工厂方法实现,但也可以使用Prototype实现
- devise开始时使用工厂方法(更简单,更可定制的子类扩展),并向需要更多灵活性的其他创build模式(更灵活,更复杂)发展。
- 工厂方法通常在模板方法中调用。
其他有用的文章:
来自sourcemaking的factory_method
来自sourcemaking的abstract_factory
来自journaldev的抽象工厂devise模式
抽象工厂的示例/场景
我住在一个雨季下雨的地方,冬天下雪,夏天又炎热又阳光。 我需要不同的衣服来保护我自己的元素。 要这样做,我去我家附近的商店,要求衣服/物品来保护自己。 店主根据我的口袋的环境和深度给我合适的物品。 他给我的物品质量和价格都是一样的。 既然他知道我的标准,那么他很容易就这样做。 但是当街对面有钱的人出现相同的要求时,他会得到一个昂贵的品牌产品。 一件值得注意的事情是他给我的所有项目在质量,标准和成本方面相互补充。 人们可以说他们一起去。 这个有钱人得到的物品也是如此。
所以通过上面的情景,我现在明白了店主的效率。 我可以用一个抽象商店取代这个店主。 我们用抽象物品获得的物品和作为透视客户的富人。 我们所需要的是适合我们需要的产品/物品。
现在我可以很容易地看到自己在考虑一个在线商店,它为众多的客户提供了一系列的服务。 每个客户属于三个组中的一个。 当一个高级团体用户打开网站时,他会得到很棒的用户界面,高度定制的广告窗格,菜单中的更多选项等等。这些相同的function集被呈现给黄金用户,但是菜单中的function较less,广告大部分相关,和lessegronomic UI。 最后是我的用户,一个“自由组”的用户。 我的服务足够让我不至于得罪了。 用户界面是一个最低限度,广告是如此之多,所以我不知道它是什么进来,最后菜单只有注销。
如果我有机会build立这样的网站,我一定会考虑抽象工厂模式。
摘要产品:广告面板,菜单,UI画家。
抽象工厂:网上商店用户体验
Concreate Factory:高级用户体验,金牌用户体验,一般用户体验。
//Abstract factory - Provides interface to create factory of related products interface PizzaIngredientsFactory{ public Dough createDough(); //Will return you family of Dough public Clam createClam(); //Will return you family of Clam public Sauce createSauce(); //Will return you family of Sauce } class NYPizzaIngredientsFactory implements PizzaIngredientsFactory{ @Override public Dough createDough(){ //create the concrete dough instance that NY uses return doughInstance; } //override other methods }
教科书定义已经由其他答案提供。 我想我也会提供一个例子。
所以这里PizzaIngredientsFactory
是一个抽象工厂,因为它提供了创build相关产品系列的方法。
请注意,Abstract工厂中的每个方法本身都是一个Factory方法 。 像createDough()
本身就是一个工厂方法,其具体实现将由像NYPizzaIngredientsFactory
这样的子类提供。 因此,使用这个不同的位置可以创build属于其位置的混凝土成分的实例。
工厂方法
提供具体实现的实例
在这个例子中:
– createDough()
– 为面团提供具体的实现。 所以这是一个工厂方法
抽象工厂
提供界面来创build相关对象的族
在这个例子中:
– PizzaIngredientsFactory
是一个抽象工厂,因为它允许创build一组相关的对象,如Dough
, Clams
, Sauce
。 为了创build每个对象族,它提供了一个工厂方法。
Head Firstdevise模式示例
也许很多人会感到惊讶,但这个问题是不正确的 。 如果你在面试中听到这个问题,你需要帮助面试官了解混淆的地方。
我们从没有被称为“工厂”的具体模式开始。 有一种叫做“抽象工厂”的模式,有一种叫做“工厂模式”的模式。
那么,“工厂”是什么意思呢? 以下之一(根据参考文献的范围,所有内容都可以被认为是正确的):
- 有些人使用它作为“ 抽象工厂 ”的别名(快捷方式)。
- 有些人使用它作为“ 工厂方法 ”的别名(快捷方式)。
- 有些人把它作为所有工厂/创作模式的通用名称。 例如“抽象工厂”和“工厂方法”都是工厂。
不幸的是 ,很多人使用“工厂”来表示另一种工厂,即创build工厂或工厂(或其接口)。 基于他们的理论:
产品实现了由Factory创build的IProduct,它实现了由AbstractFactory创build的IFactory。
要理解这是多么愚蠢,让我们继续我们的等式:
AbstractFactory实现了IAbstractFactory,它由… AbstractAbstractFactory
我希望你看到这一点。 不要混淆,请不要发明不合理的东西。
–
PS :产品的Factory是AbstractFactory,而Factory的AbstractFactory也是AbstractFactory的另一个例子。
工厂方法是一种非静态方法,它返回基类或接口types,并在层次结构中实现以启用多态创build。 工厂方法必须由类和一个或多个类的子类来定义/实现。 class级和小class每个都充当工厂。 但是,我们并不是说工厂方法就是工厂。 抽象工厂是一个用于创build相关或依赖对象系列的接口,无需指定具体的类。
抽象工厂被devise成在运行时是可替代的,所以系统可以被configuration为使用抽象工厂的具体实现者。 每个抽象工厂都是一个工厂,但不是每个工厂都是一个抽象工厂。 当需要支持创build相关或依赖对象的几个家族时,工厂而不是抽象工厂的类有时演变成抽象工厂。
我有一些要点可以用John的答案作出贡献:
抽象工厂是工厂的工厂!
使用“工厂方法”(因为“工厂”是不明确的),您可以生成一个特定界面的实现( Lemon
, Orange
等),比如IFruit
。 这个工厂可以叫做CitricFruitFactory
。
但现在你想创造另一种CitricFruitFactory不能创造的水果。 也许柠檬水果CitricFruitFactory
的代码是CitricFruitFactory
,如果你创build一个Strawberry
(草莓不是柠檬水果!)。
所以你可以创build一个名为RedFruitFactory
工厂,生产Strawberry
, Raspberry
等等。
就像John Feminella说的那样: “通过抽象工厂模式,您可以生成特定工厂界面的实现,例如IFruitFactory
,每个人都知道如何创build不同种类的水果。
IFruitFactory
实现是CitricFruitFactory
和RedFruitFactory
!
我的来源是: StackOverflow
, tutorialspoint.com
, programmers.stackexchange.com
和CodeProject.com
。
Factory Method
(也称为Factory
)用于将Interface
实现的客户端分离。 对于示例,我们有一个带有两个Circle
和Square
实现的Shape
界面。 我们已经定义了一个带有工厂方法的工厂类,这个工厂方法带有一个确定器参数,例如Type
和Shape
接口的新相关实现。
Abstract Factory
包含若干工厂实现的几个工厂方法或工厂界面。 对于上面的示例,我们有一个带有两个Red
和Yellow
实现的Color
接口。 我们定义了一个带有两个RedCircleFactory
和YellowSquareFactory
的ShapeColorFactory
接口。 下面的代码来解释这个概念:
interface ShapeColorFactory { public Shape getShapeFactory(); public Color getColorFactory(); } class RedCircleFactory implements ShapeColorFactory { @Override public Shape getShape() { return new Circle(); } @Override public Color getColor() { return new Red(); } } class YellowSquareFactory implements ShapeColorFactory { @Override public Shape getShape() { return new Square(); } @Override public Color getColor() { return new Yellow(); } }
这里FactoryMethod
和AbstractFactory
区别。 Factory Method
只是简单地返回一个接口的具体类,而Abstract Factory
返回factory of factory
。 也就是说Abstract Factory
返回一系列界面的不同组合。
我希望我的解释有用。
延伸约翰Feminella答案:
Apple
, Banana
, Cherry
实现FruitFactory
并有一个名为Create
的方法是唯一负责创build苹果或香蕉或樱桃。 你完成了,你的Factory
方法。
现在,你想从你的水果中Create
一个特殊的沙拉,有你的抽象工厂 。 抽象工厂知道如何从苹果,香蕉和樱桃中制作出特制的沙拉。
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. } }
这些工厂的主要区别是什么时候你想要什么工厂,什么时候使用它。
有时候,当你在做IOC时(例如构造函数注入的控制反转),你就知道你可以创build固体对象。 正如上面水果的例子所提到的,如果你准备好创build水果的对象,你可以使用简单的工厂模式 。
但是很多时候,你不想创build固体对象,他们会在程序stream程中稍后。 但是configuration告诉你在开始时要使用什么types的工厂,而不是创build对象,你可以把工厂从一个通用的工厂类派生到IOC中的构造器。
所以,我认为它也是关于对象的生命和创造。
按照定义,我们可以拖出两者的区别:
工厂:接口用于创build对象,但是子类决定要实例化哪个类。 对象的创build是在需要的时候完成的。
抽象工厂:抽象工厂模式作为创build其他工厂的超级工厂。 在抽象工厂模式中,一个接口负责创build一组相关的对象或依赖对象,而不指定它们的具体类。
所以,在上面的定义中,我们可以强调一个特定的区别。 即工厂模式负责创build对象,抽象工厂负责创build一组相关的对象; 显然都是通过一个界面。
工厂模式:
public interface IFactory{ void VehicleType(string n); } public class Scooter : IFactory{ public void VehicleType(string n){ Console.WriteLine("Vehicle type: " + n); } } public class Bike : IFactory{ public void VehicleType(string n) { Console.WriteLine("Vehicle type: " + n); } } public interface IVehicleFactory{ IFactory GetVehicleType(string Vehicle); } public class ConcreteVehicleFactory : IVehicleFactory{ public IFactory GetVehicleType(string Vehicle){ switch (Vehicle){ case "Scooter": return new Scooter(); case "Bike": return new Bike(); default: return new Scooter(); } } class Program{ static void Main(string[] args){ IVehicleFactory factory = new ConcreteVehicleFactory(); IFactory scooter = factory.GetVehicleType("Scooter"); scooter.VehicleType("Scooter"); IFactory bike = factory.GetVehicleType("Bike"); bike.VehicleType("Bike"); Console.ReadKey(); } }
抽象工厂模式:
interface IVehicleFactory{ IBike GetBike(); IScooter GetScooter(); } class HondaFactory : IVehicleFactory{ public IBike GetBike(){ return new FZS(); } public IScooter GetScooter(){ return new FZscooter(); } } class HeroFactory: IVehicleFactory{ public IBike GetBike(){ return new Pulsur(); } public IScooter GetScooter(){ return new PulsurScooter(); } } interface IBike { string Name(); } interface IScooter { string Name(); } class FZS:IBike{ public string Name(){ return "FZS"; } } class Pulsur:IBike{ public string Name(){ return "Pulsur"; } } class FZscooter:IScooter { public string Name(){ return "FZscooter"; } } class PulsurScooter:IScooter{ public string Name(){ return "PulsurScooter"; } } enum MANUFACTURERS { HONDA, HERO } class VehicleTypeCheck{ IBike bike; IScooter scooter; IVehicleFactory factory; MANUFACTURERS manu; public VehicleTypeCheck(MANUFACTURERS m){ manu = m; } public void CheckProducts() { switch (manu){ case MANUFACTURERS.HONDA: factory = new HondaFactory(); break; case MANUFACTURERS.HERO: factory = new HeroFactory(); break; } Console.WriteLine("Bike: " + factory.GetBike().Name() + "\nScooter: " + factory.GetScooter().Name()); } } class Program { static void Main(string[] args) { VehicleTypeCheck chk = new VehicleTypeCheck(MANUFACTURERS.HONDA); chk.CheckProducts(); chk= new VehicleTypeCheck(MANUFACTURERS.HERO); chk.CheckProducts(); Console.Read(); } }
在这里检查: http : //www.allapplabs.com/java_design_patterns/abstract_factory_pattern.htm似乎Factory方法使用一个特定的类(而不是抽象)作为基类,而抽象工厂使用抽象类。 另外,如果使用接口而不是抽象类,结果将是抽象工厂模式的不同实现。
:d
Factory Method
和Abstract Factory
保持客户与具体types的分离。 两者都创build对象,但Factory
方法使用inheritance,而Abstract Factory
使用组合。
Factory Method
在子类中被inheritance以创build具体对象(产品),而Abstract Factory
提供用于创build相关产品系列的接口以及这些接口的子类定义如何创build相关产品。
然后,这些子类在实例化时被传递到产品类中作为抽象types使用。 Abstract Factory
中的相关产品通常使用Factory Method
实施。
抽象工厂是用于创build不同types的接口的模板。 假设你有一个项目需要你parsing包含数量,价格和物品特定信息的不同types的CSV文件,比如一些包含关于巧克力以外的其他水果的数据,然后parsing后你需要在相应的数据库中更新这些信息,一个抽象工厂返回你的parsing器和修改器工厂,然后这个parsing器工厂可以返回你巧克力parsing器对象,水果parsing器对象等,同样的修饰器工厂可以返回巧克力修改器对象,水果修改器对象等。
我想我们可以通过看到一个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; } }
Now the question is which way of creation should you use and why: The first way (no pattern, just plain constructor): creating by yourself is not a good idea, you have to do all the work, and your client code is tied to the particular implementation.
The second way (using Factory pattern): provides you the benefit that you can pass any type of implementation, which can provide different type of something based on some condition (maybe a parameter passed to creational method).
The third way (using Abstract Factory pattern): This gives you more flexibility. You can find different types of creators of something based on some condition (maybe a parameter passed).
Note that you can always get away with Factory pattern by combining two conditions together (which slightly increases code complexity, and coupling), I guess that's why we rarely see real life use cases of Abstract Factory pattern.