工厂和抽象工厂都是创建型模式。
在意图和应用方面,这两种模式有什么区别?
工厂和抽象工厂都是创建型模式。
在意图和应用方面,这两种模式有什么区别?
使用工厂模式,您可以生产特定接口(例如IFruit
)的实现(例如Apple
、Banana
、Cherry
等)的实例。
而使用抽象工厂模式,则为任何人提供了一种提供自己工厂的方法。这允许您的仓库成为IFruitFactory
或IJuiceFactory
,而无需仓库了解任何关于水果或果汁的信息。
IFruit
接口——它只是实例化实现了IFruit
接口的东西。当然,工厂不一定要生产符合特定接口的实例,但如果你的工厂生产的东西彼此之间完全没有关联,那可能就存在代码问题。 - John Feminella抽象工厂模式中的方法是通过工厂方法实现的。抽象工厂模式和工厂方法模式通过抽象类型和工厂将客户端系统与实际实现类解耦。
工厂方法通过继承创建对象,而抽象工厂则通过组合创建对象。
抽象工厂模式包括AbstractFactory、ConcreteFactory、AbstractProduct、ConcreteProduct和Client。
抽象工厂模式可以使用工厂方法模式、原型模式或单例模式进行实现。ConcreteFactory对象可以作为单例实现,因为只需要一个ConcreteFactory对象实例。
工厂方法模式是抽象工厂模式的简化版本。工厂方法模式负责创建属于一组产品的对象,而抽象工厂模式则处理多个产品族。
工厂方法使用接口和抽象类来解耦客户端和生成器类以及产生的产品。抽象工厂有一个生成器作为几个工厂方法的容器,同时还有解耦客户端和生成器以及产品的接口。
当需要将客户端与所使用的特定产品解耦时,使用工厂方法模式。使用工厂方法模式可以使客户端无需创建和配置产品实例。
当需要将客户端与产品类解耦时,使用抽象工厂模式。特别适用于程序配置和修改。抽象工厂模式还可以强制实施有关哪些类必须与其他类一起使用的约束。创建新的ConcreteFactory可能是很费力的。
这个规格用于在意大利面制造机中准备不同类型的意大利面盘,是抽象工厂,而每个具体的盘子是一个工厂。
所有工厂(意大利面制造器的磁盘)都继承了抽象工厂的属性。每个单独的磁盘包含创建意大利面的信息,而意大利面制造器则没有。信息来源:http://java.dzone.com/news/intro-design-patterns-abstract
冲压设备对应抽象工厂,因为它是用于创建抽象产品对象操作的接口。冲压模具对应具体工厂,因为它们创建具体产品。每个零部件类别(引擎罩,车门等)对应抽象产品。具体元件(例如99卡美瑞的驾驶员侧门)对应具体产品。
玩具公司对应创建者,因为它可以使用工厂来创建产品对象。制造特定类型玩具(马或汽车)的玩具公司部门对应具体创建者。
工厂模式: 工厂生产 IProduct 实现
抽象工厂模式: 一个工厂-工厂生产 IFactories, 这些工厂再生产 IProducts :)
[根据评论更新]
我之前写的不正确,至少按照Wikipedia规定是这样。抽象工厂只是一个工厂接口。通过它,你可以在运行时切换工厂,以便在不同的上下文中使用不同的工厂。例如,不同操作系统、SQL提供商、中间件驱动程序等可以使用不同的工厂。
提供一个接口用于创建相关或依赖对象的家族,而不需要指定它们的具体类。
抽象工厂模式与工厂方法模式非常相似。两者之间的一个区别是,在抽象工厂模式中,一个类通过组合将对象实例化的责任委托给另一个对象,而工厂方法模式使用继承,并依赖于子类处理所需的对象实例化。
实际上,被委托的对象经常使用工厂方法来执行实例化!
工厂模式是创建型模式的示例
创建型模式抽象出对象实例化过程。它们隐藏了对象的创建方式,有助于使整个系统独立于其对象的创建和组成方式。
类创建型模式重点在于使用继承来决定要实例化的对象,即工厂方法。
对象创建型模式重点在于将实例化委托给另一个对象,即抽象工厂。
参考: 工厂模式 vs 抽象工厂模式
基本区别:
工厂:创建对象而不向客户端暴露实例化逻辑。
工厂方法:定义一个用于创建对象的接口,但让子类决定实例化哪个类。
抽象工厂:为创建相关对象族提供接口。
抽象工厂模式使用组合来委托对象创建的责任。
工厂方法模式使用继承和派生类来创建对象。
示例:StaticFactory
public class VehicleFactory {
//Vehicle factory
public static Vehicle getVehicle(String type){
if(type == null){
return null;
}
if(type.equalsIgnoreCase("Car")){
return new Car();
} else if(type.equalsIgnoreCase("Truck")){
return new Truck();
} else if(type.equalsIgnoreCase("Bicycle")){
return new Bicycle();
}
return null;
}
}
何时使用:客户端只需要一个类,不关心它得到的是哪个具体实现。
工厂方法
何时使用:客户端不知道在运行时需要创建哪些具体类,但只想获得能够完成工作的类。
抽象工厂
何时使用:当您的系统必须创建多个产品系列而不暴露实现细节时。
工厂方法:你有一个工厂,创建从特定基类派生的对象。
抽象工厂:你有一个工厂,创建其他工厂,而这些工厂又生成从基类派生的对象。你这样做是因为通常不仅想创建单个对象(与工厂方法相比),而是要创建一组相关的对象。
抽象工厂是用于创建相关对象的接口,而工厂方法则是一种方法。抽象工厂由工厂方法实现。
Product 实现了 IProduct 接口,由 Factory 创建,Factory 实现了 IFactory 接口,由 AbstractFactory 创建。
要理解这是多么荒谬,请继续我们的方程:
AbstractFactory 实现了 IAbstractFactory 接口,由……AbstractAbstractFactory???
希望你能明白这个观点。不要感到困惑,也请不要为没有原因的东西发明名称。
-
P.S.: 产品的工厂是抽象工厂,而抽象工厂的工厂也将成为抽象工厂的另一个例子。
抽象工厂示例/场景
我住在一个有雨季、冬天下雪和夏天炎热晴朗的地方。为了保护自己免受自然元素的侵害,我需要不同种类的衣物。为此,我去离家近的商店,并要求购买适合各种环境和我的经济能力的防护用品。店主根据我的标准提供我相应的物品,这些物品具有相同的质量和价位范围。由于他了解我的标准,所以很容易做到这一点。但是当来自街对面的富人有同样的需求时,他会得到昂贵的名牌商品。值得注意的是,他给我所有的物品在质量、标准和成本方面都相互补充。可以说它们彼此搭配。富人得到的物品也是如此。
通过上述情况的观察,我现在欣赏店主的效率。我可以将这个店主替换为抽象店铺。我们使用抽象产品与我和富人作为潜在客户获取物品。我们只需要适合我们需求的产品/物品。
现在,我可以很容易地想象自己考虑一个为其大量客户提供一套服务的在线商店。每个客户都属于三个群体中的一个。当一个高级用户打开该网站时,他会得到出色的用户界面、高度定制的广告窗格、菜单中更多的选项等等。这些同样的功能也被呈现给金牌用户,但是菜单中的功能较少,广告主要与相关内容相关,用户界面略显笨拙。最后是我这类‘免费组’用户, 我只需获得足够的服务以避免冒犯。用户界面是最基本的, 广告不知所云, 菜单只有登出。
如果我有机会构建像这样的网站,我肯定会考虑抽象工厂模式。
抽象产品: 广告窗格,菜单,用户界面。
抽象工厂: 网上商店用户体验
具体工厂:高级用户体验、金牌用户体验、普通用户体验。
//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
是一个抽象工厂,因为它提供了创建一组相关产品的方法。
请注意,抽象工厂中的每个方法本身都是一个工厂方法。例如,createDough()
本身就是一个工厂方法,其具体实现将由子类如 NYPizzaIngredientsFactory
提供。因此,使用这种方式,每个不同的位置都可以创建属于其位置的具体成分实例。
提供具体实现的实例
例如:
- createDough()
- 提供了面团的具体实现。因此这是一个工厂方法。
提供接口以创建相关对象的族群
例如:
- PizzaIngredientsFactory
是一个抽象工厂,因为它允许创建一组相关的对象,如 Dough
、Clams
、Sauce
。对于创建每个对象族群,它提供了一个工厂方法。
摘自《Head First设计模式》中的示例。
createThing()
),而抽象工厂使用组合(间接性是水平的,例如getFactory().createThing()
)。 - David James