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

我知道有很多关于这两种模式之间差异的帖子,但有一些东西我找不到。

从我所阅读的内容中,我发现工厂方法模式允许您定义如何创建单个具体产品,但对客户隐藏实现,因为他们将看到通用产品。我的第一个问题是关于抽象工厂。它的角色是否允许您在其中创建一系列具体对象(这取决于您使用的具体工厂),而不仅仅是单个具体对象?根据调用的方法,抽象工厂只返回一个非常大的对象还是多个对象?

我最后两个问题是关于一句我在很多地方都见过的引语,我不能完全理解:

两者之间的一个区别是 使用抽象工厂模式,a 类委托的责任 对象实例化到另一个对象 通过合成,而工厂 方法模式使用继承和 类依赖于子类来处理 需要的对象实例化

我的理解是,工厂方法模式有一个Creator接口,它将使ConcreteCreator负责知道要实例化哪个ConcreteProduct。这就是使用继承来处理对象实例化的意思吗?

现在,关于引用,抽象工厂模式是如何通过组合将对象实例化的责任委托给另一个对象的?这是什么意思?在我看来,抽象工厂模式似乎也使用继承来完成构造过程,但我仍然在学习这些模式。

任何帮助,特别是最后一个问题,将非常感激。

281486 次浏览

两者的区别

“工厂方法”与“工厂方法”的主要区别是:而“抽象工厂”;工厂方法是一个方法,而抽象工厂是一个对象。我想很多人都把这两个词搞混了,开始交替使用。我记得当我学习它们的时候,我很难找到它们之间的确切区别。

因为工厂方法只是一个方法,它可以在子类中被重写,因此引用的后半部分:

< p >…工厂方法模式使用的 继承并依赖于一个子类 来处理所需的对象 实例化。< / p >

引用假设这里有一个对象正在调用自己的工厂方法。因此,唯一可以改变返回值的是子类。

抽象工厂是一个具有多个工厂方法的对象。看看你引言的前半部分:

< p >…使用抽象工厂模式,一个类 委托对象的职责 实例化到另一个对象 作文…< / p >

他们说的是,有一个对象A,想要创建一个Foo对象。而不是创建Foo对象本身(例如,使用工厂方法),它将获得一个不同的对象(抽象工厂)来创建Foo对象。

代码示例

为了向你展示区别,这里有一个正在使用的工厂方法:

class A {
public void doSomething() {
Foo f = makeFoo();
f.whatever();
}


protected Foo makeFoo() {
return new RegularFoo();
}
}


class B extends A {
protected Foo makeFoo() {
//subclass is overriding the factory method
//to return something different
return new SpecialFoo();
}
}

这是一个正在使用的抽象工厂:

class A {
private Factory factory;


public A(Factory factory) {
this.factory = factory;
}


public void doSomething() {
//The concrete class of "f" depends on the concrete class
//of the factory passed into the constructor. If you provide a
//different factory, you get a different Foo object.
Foo f = factory.makeFoo();
f.whatever();
}
}


interface Factory {
Foo makeFoo();
Bar makeBar();
Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}


//need to make concrete factories that implement the "Factory" interface here

抽象工厂创建一个具有抽象方法的基类,为应该创建的对象定义方法。派生基类的每个工厂类都可以创建每种对象类型的自己的实现。

enter image description here

工厂方法只是一个用于在类中创建对象的简单方法。它通常添加在聚合根中(Order类有一个名为CreateOrderLine的方法)

enter image description here

抽象工厂

在下面的示例中,我们设计了一个接口,这样我们就可以将队列创建与消息传递系统分离,因此可以为不同的队列系统创建实现,而不必更改代码库。

interface IMessageQueueFactory
{
IMessageQueue CreateOutboundQueue(string name);
IMessageQueue CreateReplyQueue(string name);
}


public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
IMessageQueue CreateOutboundQueue(string name)
{
//init queue
return new AzureMessageQueue(/*....*/);
}


IMessageQueue CreateReplyQueue(string name)
{
//init response queue
return new AzureResponseMessageQueue(/*....*/);
}


}


public class MsmqFactory : IMessageQueueFactory
{
IMessageQueue CreateOutboundQueue(string name)
{
//init queue
return new MsmqMessageQueue(/*....*/);
}


IMessageQueue CreateReplyQueue(string name)
{
//init response queue
return new MsmqResponseMessageQueue(/*....*/);
}
}

工厂方法

HTTP服务器的问题在于,我们总是需要为每个请求提供响应。

public interface IHttpRequest
{
// .. all other methods ..


IHttpResponse CreateResponse(int httpStatusCode);
}

如果没有工厂方法,HTTP服务器用户(即程序员)将被迫使用特定于实现的类,这就违背了IHttpRequest接口的目的。

因此,我们引入工厂方法,以便响应类的创建也被抽象出来。

总结

区别在于类的目的包含一个工厂方法不是创建对象吗,而抽象工厂应该只用于创建对象。

使用工厂方法时应该小心,因为在创建对象时很容易破坏LSP (利斯科夫替换原理)。

AbstractFactory和Factory设计模式之间的区别如下:

  • 工厂方法只用于创建一个产品,而抽象工厂用于创建一系列相关或依赖的产品。
  • 工厂方法模式向客户端公开了一个方法来创建对象,而在抽象工厂模式中,它们公开了一系列相关的对象,这些对象可能由这些Factory方法组成。
  • 工厂方法模式隐藏单个对象的构造,而抽象工厂模式隐藏一系列相关对象的构造。抽象工厂通常使用(一组)工厂方法来实现。
  • 抽象工厂模式使用组合将创建对象的责任委托给另一个类,而工厂方法设计模式使用继承并依赖于派生类或子类来创建对象。
  • 工厂方法模式背后的思想是,它允许这样的情况:客户端不知道在运行时需要创建哪些具体的类,但只想获得一个可以完成工作的类,而抽象工厂模式在系统必须创建多个产品系列或您想提供一个产品库而不暴露实现细节时得到最佳利用。

工厂方法模式实现: 工厂方法UML

抽象工厂模式实现:

抽象工厂UML

抽象工厂是创建相关产品的接口,而工厂方法只是一种方法。抽象工厂可以通过多种工厂方法实现。

抽象工厂UML

让我们明确一点,在生产代码中,大多数时候我们使用抽象工厂模式,因为类A是用接口b编程的,而A需要创建b的实例,因此A必须有一个工厂对象来生成b的实例,因此A不依赖于b的任何具体实例,希望它有帮助。

  1. 我的第一个问题是关于抽象工厂。它的角色是否允许您在其中创建一系列具体对象(这取决于您使用的具体工厂),而不仅仅是单个具体对象?

是的。抽象工厂的目的是:

提供一个接口,用于创建一系列相关或依赖的对象,而无需指定它们的具体类。


  1. 根据调用的方法,抽象工厂只返回一个非常大的对象还是多个对象?

# EYZ0

  1. 我的理解是,工厂方法模式有一个Creator接口,它将使ConcreteCreator负责知道要实例化哪个ConcreteProduct。这就是使用继承来处理对象实例化的意思吗?

# EYZ0

  1. 抽象工厂模式委托对象实例化的责任通过组合到另一个对象?这是什么意思?

# EYZ0 # EYZ1。

你可以在SE的相关文章中找到更多细节:

工厂模式和抽象工厂模式的基本区别是什么?< / >

设计模式:工厂vs工厂方法vs抽象工厂

比起工厂方法,我更喜欢抽象工厂。从Tom Dalling上面的例子(顺便说一句,解释得很好)中,我们可以看到抽象工厂是更可组合的,因为我们所需要做的只是将一个不同的工厂传递给构造函数(这里使用构造函数依赖注入)。但是工厂方法要求我们引入一个新类(需要管理更多的东西)并使用子类化。总是选择组合而不是继承。

< p > # EYZ0 < p > 假设您正在构建一个工具,其中包含对象和对象之间相互关系的具体实现。由于您预见到了对象中的变化,因此通过将创建对象的变量的责任分配给另一个对象(我们称之为抽象工厂),您创建了一个间接性。这种抽象有很大的好处,因为您可以预见到未来的扩展需要这些对象的变体。< p > 在这一思路中,另一个相当有趣的动机是,整个群体中的所有对象都有相应的变体。基于某些条件,将使用任意一种变体,并且在每种情况下,所有对象必须具有相同的变体。这可能有点违反直觉,因为我们经常倾向于认为——只要对象的变体遵循一个公共的统一契约(广义上的接口),具体的实现代码就永远不会中断。这里有趣的事实是,这并不总是正确的,特别是当预期的行为不能通过编程契约建模时。< p > 一个简单的(借鉴了GoF的理念)是任何GUI应用程序,比如模拟MS、Mac或Fedora OS的外观的虚拟监视器。例如,当所有窗口、按钮等小部件对象都具有MS变体,而滚动条则派生自MAC变体时,该工具的目的就会严重失败。< p > 以上这些情况构成了抽象工厂模式的基本需求。

另一方面,假设您正在编写一个框架,以便许多人可以使用您的框架构建各种工具(比如上面例子中的那个)。根据框架的思想,您不需要这样做,尽管您不能在逻辑中使用具体对象。而是在各种对象之间以及它们如何交互之间放置一些高级契约。当您(作为框架开发人员)仍然停留在非常抽象的级别时,工具的每个构建者都被迫遵循您的框架构造。然而,他们(工具构建者)可以自由地决定构建什么对象以及他们创建的所有对象将如何交互。与之前的情况(抽象工厂模式)不同,您(作为框架创建者)在这种情况下不需要使用具体对象;而是停留在客体的契约层面。此外,与前面动机的第二部分不同,您或工具构建者永远不会遇到混合来自变体的对象的情况。在这里,虽然框架代码仍然处于契约级别,但每个工具构建者都被限制使用他们自己的对象(由案件本身的性质决定)。在这种情况下,对象创建委托给每个实现者,框架提供者只是提供了创建和返回对象的统一方法。这样的方法对于框架开发人员来说是不可避免的,并且有一个特殊的名字叫做工厂方法 (底层模式的工厂方法模式)。< p > # EYZ0 < /强> < p >

  • 如果你熟悉“模板方法”,那么你就会发现,在任何形式的框架程序中,工厂方法都经常从模板方法中调用。相比之下,应用程序的模板方法往往是具体算法的简单实现,没有工厂方法。
  • 此外,为了思想的完整性,使用框架(上面提到的),当工具构建者在每个工厂方法中构建工具时,他/她可以进一步将责任委托给抽象工厂对象,而不是创建具体对象,前提是工具构建者预见到具体对象的变化以供将来扩展。

# EYZ0

//Part of framework-code
BoardGame {
Board createBoard() //factory method. Default implementation can be provided as well
Piece createPiece() //factory method


startGame(){        //template method
Board borad = createBoard()
Piece piece = createPiece()
initState(board, piece)
}
}




//Part of Tool-builder code
Ludo inherits  BoardGame {
Board createBoard(){ //overriding of factory method
//Option A: return new LudoBoard() //Lodu knows object creation
//Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
}
….
}


//Part of Tool-builder code
Chess inherits  BoardGame {
Board createBoard(){ //overriding of factory method
//return a Chess board
}
….
}

# EYZ0

电信公司提供什么?例如宽带,电话线和移动电话,你被要求创建一个应用程序,向他们的客户提供他们的产品。

一般来说,你在这里要做的是,创建产品,即宽带,电话线和移动是通过你的工厂方法,你知道什么属性,你有这些产品,这是相当直接的。

现在,该公司想要为他们的客户提供他们的产品捆绑,即宽带、电话线和移动设备,而抽象工厂来了。

换句话说,抽象工厂是由其他负责创造自己产品的工厂组成的,抽象工厂知道如何在自己的责任方面将这些产品置于更有意义的位置。

在这种情况下,BundleFactory是抽象工厂,BroadbandFactoryPhonelineFactoryMobileFactoryFactory。为了进一步简化,这些工厂将使用工厂方法来初始化单个产品。

运行下面的代码示例:

public class BroadbandFactory : IFactory {
public static Broadband CreateStandardInstance() {
// broadband product creation logic goes here
}
}


public class PhonelineFactory : IFactory {
public static Phoneline CreateStandardInstance() {
// phoneline product creation logic goes here
}
}


public class MobileFactory : IFactory {
public static Mobile CreateStandardInstance() {
// mobile product creation logic goes here
}
}


public class BundleFactory : IAbstractFactory {


public static Bundle CreateBundle() {
broadband = BroadbandFactory.CreateStandardInstance();
phoneline = PhonelineFactory.CreateStandardInstance();
mobile = MobileFactory.CreateStandardInstance();


applySomeDiscountOrWhatever(broadband, phoneline, mobile);
}


private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
// some logic here
// maybe manange some variables and invoke some other methods/services/etc.
}
}

希望这能有所帮助。

使它非常简单,最小的接口&请聚焦"//1":

class FactoryProgram
{
static void Main()
{
object myType = Program.MyFactory("byte");
Console.WriteLine(myType.GetType().Name);


myType = Program.MyFactory("float"); //3
Console.WriteLine(myType.GetType().Name);


Console.ReadKey();
}


static object MyFactory(string typeName)
{
object desiredType = null; //1
switch (typeName)
{
case "byte": desiredType = new System.Byte(); break; //2
case "long": desiredType = new System.Int64(); break;
case "float": desiredType = new System.Single(); break;
default: throw new System.NotImplementedException();
}
return desiredType;
}
}

这里的要点:1。工厂,工厂机制必须使用继承(System。对象->字节,浮点…所以如果你在程序中有继承,那么根据设计2,工厂(抽象工厂很可能不在那里)已经在那里了。Creator (MyFactory)知道具体类型,因此返回具体类型对象给调用者(Main);在抽象工厂中,返回类型是一个接口。

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
{
IVehicle CreateSingleVehicle(string vehicleType);
}
class HondaFactory : IVehicleFactory
{
public IVehicle CreateSingleVehicle(string vehicleType)
{
switch (vehicleType)
{
case "Sports": return new SportsBike();
case "Regular":return new RegularBike();
default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
}
}
}
class HeroFactory : IVehicleFactory
{
public IVehicle CreateSingleVehicle(string vehicleType)
{
switch (vehicleType)
{
case "Sports":  return new SportsBike();
case "Scooty": return new Scooty();
case "DarkHorse":return new DarkHorseBike();
default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
}
}
}


class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }


class Program
{
static void Main(string[] args)
{
IVehicleFactory honda = new HondaFactory(); //1
RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);


IVehicleFactory hero = new HeroFactory();
DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);


Console.ReadKey();
}
}

重点:1、要求:本田将创造“普通”,“运动”,而Hero将创造“黑马”,“运动”和“Scooty”。2. 为什么是两个接口?一个用于制造商类型(IVehicleFactory),另一个用于产品工厂(IVehicle);另一种理解接口的方法是抽象工厂是关于创建相关对象的。问题是IVehicleFactory的子代返回和IVehicle(而不是工厂中的混凝土);我得到父变量IVehicle;然后我通过调用CreateSingleVehicle创建实际的具体类型,然后将父对象转换为实际的子对象。如果我执行RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");;你会得到ApplicationException,这就是为什么我们需要通用抽象工厂,如果需要我会解释。希望它能帮助初学者到中级观众。

现实生活中的例子。(容易记)

工厂

想象一下,你正在建造一所房子,你找一个木匠开一扇门。你给他门的尺寸和你的要求,他就会为你造一扇门。在这种情况下,木匠是门的工厂。你的规格是工厂的输入,门是工厂的输出或产品。

抽象工厂

现在,考虑同样的门的例子。你可以去找木匠,也可以去塑料门店或PVC店。他们都是门厂。根据情况,你决定你需要接触什么样的工厂。这就像一个抽象工厂。

我在这里解释了工厂方法模式和抽象工厂模式,从不使用它们来解释问题开始,然后使用上面的模式来解决问题 # EYZ0 < / p >

请允许我准确地说。大多数答案都已经解释过了,还提供了图表和例子。

所以我的回答就是一句话。我自己的话:抽象工厂模式在抽象层上添加到多个工厂方法实现之上。它表示抽象工厂包含或复合包含一个或多个工厂方法模式"

之前的很多回答都没有提供抽象工厂和工厂方法模式之间的代码比较。下面是我试图用Java来解释它。我希望它能帮助那些需要简单解释的人。

正如GoF所说:抽象工厂提供了一个接口,用于创建相关或依赖的对象族,而无需指定 它们的具体类。

public class Client {
public static void main(String[] args) {
ZooFactory zooFactory = new HerbivoreZooFactory();
Animal animal1 = zooFactory.animal1();
Animal animal2 = zooFactory.animal2();
animal1.sound();
animal2.sound();


System.out.println();


AnimalFactory animalFactory = new CowAnimalFactory();
Animal animal = animalFactory.createAnimal();
animal.sound();
}
}

public interface Animal {
public void sound();
}


public class Cow implements Animal {


@Override
public void sound() {
System.out.println("Cow moos");
}
}


public class Deer implements Animal {


@Override
public void sound() {
System.out.println("Deer grunts");
}


}


public class Hyena implements Animal {


@Override
public void sound() {
System.out.println("Hyena.java");
}


}


public class Lion implements Animal {


@Override
public void sound() {
System.out.println("Lion roars");
}


}

public interface ZooFactory {
Animal animal1();


Animal animal2();
}


public class CarnivoreZooFactory implements ZooFactory {


@Override
public Animal animal1() {
return new Lion();
}


@Override
public Animal animal2() {
return new Hyena();
}


}


public class HerbivoreZooFactory implements ZooFactory {


@Override
public Animal animal1() {
return new Cow();
}


@Override
public Animal animal2() {
return new Deer();
}


}

public interface AnimalFactory {
public Animal createAnimal();
}


public class CowAnimalFactory implements AnimalFactory {


@Override
public Animal createAnimal() {
return new Cow();
}


}


public class DeerAnimalFactory implements AnimalFactory {


@Override
public Animal createAnimal() {
return new Deer();
}


}


public class HyenaAnimalFactory implements AnimalFactory {


@Override
public Animal createAnimal() {
return new Hyena();
}


}


public class LionAnimalFactory implements AnimalFactory {


@Override
public Animal createAnimal() {
return new Lion();
}


}

抽象工厂和工厂方法的主要区别是:抽象工厂是由Composition实现的;但是# EYZ1。

是的,你没有看错:这两种模式之间的主要区别是旧的组合vs继承辩论。

UML图可以在(GoF)书中找到。我想提供代码示例,因为我认为将本文中前两个答案中的示例结合起来会比单独一个答案提供更好的演示。此外,我在类名和方法名中使用了书中的术语。

抽象工厂

    这里要掌握的最重要的一点是抽象工厂 将注射放入客户端。这就是为什么我们说抽象 Factory是由Composition实现的。通常是依赖项注入 框架将执行该任务;但框架不是必需的 李DI。< / > 第二个关键点是这里的混凝土工厂是 不是工厂方法实现!工厂的示例代码 方法。 最后,要注意的第三点是之间的关系 产品:在本例中是出站队列和应答队列。一个具体 factory生产Azure队列,另一个MSMQ。GoF指 这种产品关系就像一个“家庭”,这很重要 注意在这种情况下family并不意味着类层次结构
public class Client {
private final AbstractFactory_MessageQueue factory;


public Client(AbstractFactory_MessageQueue factory) {
// The factory creates message queues either for Azure or MSMQ.
// The client does not know which technology is used.
this.factory = factory;
}


public void sendMessage() {
//The client doesn't know whether the OutboundQueue is Azure or MSMQ.
OutboundQueue out = factory.createProductA();
out.sendMessage("Hello Abstract Factory!");
}


public String receiveMessage() {
//The client doesn't know whether the ReplyQueue is Azure or MSMQ.
ReplyQueue in = factory.createProductB();
return in.receiveMessage();
}
}


public interface AbstractFactory_MessageQueue {
OutboundQueue createProductA();
ReplyQueue createProductB();
}


public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
@Override
public OutboundQueue createProductA() {
return new AzureMessageQueue();
}


@Override
public ReplyQueue createProductB() {
return new AzureResponseMessageQueue();
}
}


public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
@Override
public OutboundQueue createProductA() {
return new MsmqMessageQueue();
}


@Override
public ReplyQueue createProductB() {
return new MsmqResponseMessageQueue();
}
}

工厂方法

    这里要掌握的最重要的一点是ConcreteCreator . # 客户端。换句话说,客户端是一个子类,其父类定义了factoryMethod()。这就是为什么我们这么说 工厂方法由继承实现 第二个关键点是要记住Factory Method 模式只不过是模板方法的专门化 模式。这两种模式共享相同的结构。他们只 目的不同。工厂方法是创造性的(它构建 而模板方法是行为的(它计算 李的东西)。< / > 最后,要注意的第三点是Creator (parent) 类调用它自己的factoryMethod()。如果我们移除 从父类中删除anOperation(),只留下一个方法 在后面,它不再是工厂方法模式。换句话说, 中少于两个方法不能实现工厂方法 父类;其中一个必须调用另一个
public abstract class Creator {
public void anOperation() {
Product p = factoryMethod();
p.whatever();
}


protected abstract Product factoryMethod();
}


public class ConcreteCreator extends Creator {
@Override
protected Product factoryMethod() {
return new ConcreteProduct();
}
}

混杂。,杂项工厂图案

请注意,尽管GoF定义了两种不同的工厂模式,但它们并不是唯一存在的工厂模式。它们甚至不一定是最常用的工厂模式。第三个著名的例子是Josh Bloch的《Effective Java》中的静态工厂模式。《头部优先设计模式》一书还包括另一种被称为简单工厂的模式。

不要落入假设每个工厂模式都必须匹配GoF中的一个模式的陷阱。

工厂方法依赖于继承:对象创建被委托给子类,子类实现了创建对象的工厂方法。

< em >抽象工厂< / em >依赖于对象组合:对象创建在工厂接口中公开的方法中实现。

工厂和抽象工厂模式的高级图表,

diagram

有关Factory方法的更多信息,请参阅这篇文章

有关抽象工厂方法的更多信息,请参阅这篇文章

抽象工厂:一个工厂的工厂;将独立但相关/依赖的工厂分组在一起,而不指定它们的具体类的工厂。 # EYZ0 < / p >

工厂:它提供了一种将实例化逻辑委托给子类的方法。 # EYZ0 < / p >

抽象工厂设计模式:什么是抽象工厂设计模式?它类似于工厂方法设计模式。当我们有多个工厂时,我们需要使用这种模式。在此模式中将定义一组工厂。工厂方法模式是抽象工厂设计模式的子集。它们具有与工厂模式相同的优点。抽象工厂依赖于对象组合,而工厂方法处理继承。 工厂设计模式在Java中的实时示例:什么是工厂设计模式?它主要用于面向对象编程的设计。这是一种创造模式。这都是关于创建实例的。客户端创建对象时不会暴露对象创建逻辑。它被广泛应用于不同的框架中,例如spring框架。当类不知道它必须创建的另一个对象时,我们使用这种模式。 实时例子:当我们的车在路上抛锚时。我们需要告知修理工我们使用的是什么类型的车辆,以便修理工携带工具进行维修。根据我们的输入,维修人员将解决问题,并为我们再次旅行做好准备。 有一些内置方法使用这些模式。示例JavaUtilcalendar类中的getInstance()方法。在getInstance()的帮助下,我们可以在执行此方法时获取对象。 getInstance()是方法返回对象。 # EYZ0 < / p >

有相当多的定义。基本上,描述< >强工厂模式< / >强的三种常见方式是

  1. 简单的工厂

基于条件的简单对象创建方法/类。

  1. 工厂方法

使用子类提供实现的工厂方法设计模式。

  1. 抽象工厂

抽象工厂设计模式产生相关或依赖的对象族,而不指定它们的具体类。

下面的链接非常有用——工厂比较- refactoring.guru

工厂设计模式

generation 1 <- generation 2 <- generation 3
//example
(generation 1) shape <- (generation 2) rectangle, oval <- (generation 3) rectangle impressionism, rectangle surrealism, oval impressionism, oval surrealism

工厂

用例:实例化generation 2一个对象

它是一个Creational模式,允许您在一个简单的地方创建generation 2。它符合SRP和OCP -所有的更改都在一个类中进行。

enum ShapeType {
RECTANGLE,
OVAL
}


class Shape {}


//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}


//Factory
class Factory {
Shape createShape(ShapeType type) {


switch (type) {
case RECTANGLE:
return new Rectangle();
case OVAL:
return new Oval();
}
}
}


//Creator
class Painter {


private Factory factory;


Painter(Factory factory) {
this.factory = factory;
}


Shape prepareShape(ShapeType type) {
return factory.createShape(type);
}
}


//using
class Main {
void main() {
Painter painter = new Painter(new Factory());


Shape shape1 = painter.prepareShape(ShapeType.RECTANGLE);
Shape shape2 = painter.prepareShape(ShapeType.OVAL);
}
}

工厂方法

用例:实例化generation 3一个对象

有助于与下一代家庭成员合作。每个画家都有自己的风格,印象派、超现实主义……Factory Method使用抽象的Creator作为工厂(抽象方法),Concrete Creators是该方法的实现

enum ShapeType {
RECTANGLE,
OVAL
}


class Shape {}


//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}


//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}


//Creator
abstract class Painter {


Shape prepareShape(ShapeType type) {
return createShape(type);
}


//Factory method
abstract Shape createShape(ShapeType type);
}


//Concrete Creators
class PainterImpressionism {


@override
Shape createShape(ShapeType type) {
switch (type) {
case RECTANGLE:
return new RectangleImpressionism();
case OVAL:
return new OvalImpressionism();
}
}
}


class PainterSurrealism {


@override
Shape createShape(ShapeType type) {
switch (type) {
case RECTANGLE:
return new RectangleSurrealism();
case OVAL:
return new OvalSurrealism();
}
}
}


//using
class Main {
void main() {
Painter painterImpressionism = new PainterImpressionism();
Shape shape1 = painterImpressionism.prepareShape(ShapeType.RECTANGLE);


Painter painterSurrealism = new PainterSurrealism();
Shape shape2 = painterSurrealism.prepareShape(ShapeType.RECTANGLE);
}
}


抽象工厂

用例:实例化generation 3所有对象

Factory是抽象Factory和实现Concrete Factories的一部分


//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}


//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}


//Abstract Factory
interface Factory {
Rectangle createRectangle();
Oval createOval();
}


//Concrete Factories
class ImpressionismFactory implements Factory {
@Override
public Rectangle createRectangle() {
return new RectangleImpressionism();
}


@Override
public Oval createOval() {
return new OvalImpressionism();
}
}


class SurrealismFactory implements Factory {
@Override
public Rectangle createRectangle() {
return new RectangleSurrealism();
}


@Override
public Oval createOval() {
return new OvalSurrealism();
}
}


//Creator
class Painter {


Rectangle rectangle;
Oval oval;


Painter(Factory factory) {
rectangle = factory.createRectangle();
rectangle.resize();


oval = factory.createOval();
oval.resize();
}
}


//using
class Main {
void main() {
Painter painter1 = new Painter(new ImpressionismFactory());
Shape shape1 = painter1.rectangle;
Shape shape2 = painter1.oval;


Painter painter2 = new Painter(new ImpressionismFactory());
Shape shape3 = painter2.rectangle;
Shape shape4 = painter1.oval;
}
}

A)工厂方法模式

工厂方法是一种创建设计模式,它提供了创建对象的接口,但允许子类改变将要创建的对象的类型。

如果在基类和扩展它的子类中有一个创建方法,您可能会考虑工厂方法。

B)抽象工厂模式

抽象工厂是一种创造性的设计模式,允许在不指定具体类的情况下产生相关或依赖的对象族。

什么是“对象族”?例如,以这组类为例:传输+引擎+控制。这些可能有几种变体:

1-汽车+内燃机+方向盘

2-平面+ JetEngine +轭

如果你的程序不使用产品族,那么你就不需要抽象工厂。

同样,很多人混淆了抽象工厂模式和简单的工厂类声明为抽象。不要那样做!

裁判:# EYZ0

据我估计,@TomDalling给出的答案确实是正确的(不管它有什么价值),但是评论中似乎仍然有很多困惑。

我在这里所做的是为这两种模式创建一些略显非典型的示例,并试图使它们乍一看非常相似。这将有助于查明将它们分开的关键差异。

# EYZ0 # EYZ1

如果您对这些模式完全不熟悉,那么这些示例可能不是最好的开始。

工厂方法

enter image description here

Client.javaish

Client(Creator creator) {
ProductA a = creator.createProductA();
}

Creator.javaish

Creator() {}


void creatorStuff() {
ProductA a = createProductA();
a.doSomething();
ProductB b = createProductB();
b.doStuff();
}


abstract ProductA createProductA();


ProductB createProductB() {
return new ProductB1();
}

为什么有CreatorClient?

为什么不呢?FactoryMethod可以与两者一起使用,但是Creator的类型将决定所创建的特定产品。

为什么createProductBCreator中不是抽象的?

可以提供默认实现,子类仍然可以覆盖该方法以提供自己的实现。

我以为工厂方法只生产一种产品?

每个方法只返回一个产品,但创建者可以使用多个工厂方法,只是它们不一定以任何特定的方式相关。

抽象工厂

enter image description here

Client.javaish

AbstractFactory factory;


Client() {
if (MONDAY) {
factory = new Factory2();
} else {
factory = new AbstractFactory();
}
}


void clientStuff() {
ProductA a = factory.createProductA();
a.doSomething();
ProductB b = factory.createProductB();
b.doStuff();
}

等等!你的AbstractFactory不是,嗯……er # EYZ1

没关系,我们仍然提供接口。创建方法上的返回类型是我们想要制作的产品的超类型。

圣烟蝙蝠侠!Factory2没有覆盖createProductA(),“产品族”发生了什么?

模式中并没有说一个对象不能属于一个以上的家族(尽管您的用例可能禁止这样做)。每个混凝土工厂负责决定哪些产品可以一起生产。

这是不对的,Client没有使用依赖注入

你必须决定你的具体类将在某个地方,Client仍然被写入AbstractFactory接口。

这里的困惑是人们把作文依赖注入混为一谈。Client有一个AbstractFactory,不管它是怎么得到的。与IS-A关系相比,ClientAbstractFactory之间没有继承关系。

关键的不同点

  • 抽象工厂总是关于对象的家族
  • 工厂方法只是允许子类化的一个方法,用于指定具体对象的类型
  • 抽象工厂为客户端提供了一个接口,它与产品的使用位置是分开的,工厂方法可以由创建者自己使用,也可以暴露给客户端。

总结

工厂的目的是为客户端或工厂本身提供对象。

创建者有自己的职责,可能需要使用对象或将对象传递给客户端

定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。——GoF

抽象工厂:

提供一个接口来创建相关或依赖的对象族,而不指定它们的具体类。——GoF


PlantUML代码,如果你想玩图:

@startuml FactoryMethod
abstract class Creator {
creatorStuff()
{abstract} createProductA(): ProductA
createProductB(): ProductB
}
class Creator1 {
createProductA(): ProductA
}
class Creator2 {
createProductA(): ProductA
createProductB(): ProductB
}


together {
interface ProductA {
doSomething()
}
class ProductA1
' class Product1B
}
together {
interface ProductB {
doStuff()
}
class ProductB1
class ProductB2
}
Client --> Creator


Creator <|-- Creator1
Creator <|-- Creator2


Creator --> ProductB1
ProductA1 <-- Creator1
ProductA1 <-- Creator2
ProductB2 <-- Creator2


ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2


ProductA <- Creator


@enduml
@startuml AbstractFactory


together {
interface ProductA {
doSomething()
}
class ProductA1
}


together {
interface ProductB {
doStuff()
}
class ProductB1
class ProductB2
}


class AbstractFactory {
createProductA(): ProductA
createProductB(): ProductB
--
-
}


class Factory2 {
createProductB(): ProductB
}


Client --> AbstractFactory
AbstractFactory <|-- Factory2


ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2


AbstractFactory --> ProductA1
AbstractFactory --> ProductB1
ProductB2 <-- Factory2


@enduml

我的结论:没有区别。为什么?因为我看不出有任何理由为工厂以外的对象配备工厂方法——否则就违反了责任分离原则。此外,我看不出具有单一工厂方法的工厂和具有多个工厂方法的工厂之间有任何区别:两者都创建“相关对象的家族”。除非有人能证明只有一个家庭成员的家庭不是一个家庭。或者包含单个项的集合不是集合。