抽象工厂和工厂设计模式有什么区别?

What are the differences between Abstract Factory and Factory design patterns?

我知道有很多关于这两种模式之间差异的文章,但是有一些事情我找不到。

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

我最后的两个问题是关于一个单引号,我无法完全理解我在许多地方看到的:

One difference between the two is that
with the Abstract Factory pattern, a
class delegates the responsibility of
object instantiation to another object
via composition whereas the Factory
Method pattern uses inheritance and
relies on a subclass to handle the
desired object instantiation.

我的理解是工厂方法模式有一个创建者接口,它将使具体创建者负责知道要实例化哪个具体产品。这就是使用继承来处理对象实例化的含义吗?

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

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


两者的区别

"工厂方法"和"抽象工厂"的主要区别在于工厂方法是一个单一的方法,而抽象工厂是一个对象。我认为很多人会混淆这两个术语,并开始交替使用它们。我记得我很难准确地发现我学到它们时的区别。

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

... the Factory Method pattern uses
inheritance and relies on a subclass
to handle the desired object
instantiation.

引号假设一个对象正在调用它自己的工厂方法。因此,唯一能改变返回值的是一个子类。

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

... with the Abstract Factory pattern, a class
delegates the responsibility of object
instantiation to another object via
composition ...

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

代码示例

为了说明区别,这里使用的是工厂方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
    }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

抽象工厂

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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服务器中的问题是,我们总是需要对每个请求进行响应。

1
2
3
4
5
6
public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

如果没有factory方法,HTTP服务器用户(即程序员)将被迫使用特定于实现的类,这会破坏IHttpRequest接口的目的。

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

总结

不同之处在于,包含工厂方法的类的预期目的不是创建对象,而抽象工厂只应用于创建对象。

在使用工厂方法时应该小心,因为在创建对象时很容易打破LSP(Liskov替换原则)。


抽象工厂和工厂设计模式的区别如下:

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

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

抽象工厂模式实现:

Abstract Factory UML


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

Abstract Factory UML


抽象工厂和工厂方法的主要区别在于抽象工厂是通过组合实现的,而工厂方法是通过继承实现的。

是的,您正确地理解了这一点:这两种模式的主要区别在于旧的组合与继承的争论。

UML图可以在(gof)书中找到。我想提供代码示例,因为我认为将这个线程中前两个答案中的示例组合在一起比单独给出任何一个答案都能提供更好的演示。此外,我在类名和方法名中使用了本书中的术语。

抽象工厂

  • 这里最重要的一点是要理解抽象工厂注入到客户端。这就是为什么我们说这个摘要工厂是通过组合来实现的。通常,依赖注入框架将执行该任务;但不需要框架DI。
  • 第二个关键点是这里的混凝土工厂不是工厂方法实现!工厂代码示例方法如下所示。
  • 最后,要注意的第三点是产品:在这种情况下,出站和应答队列。一混凝土工厂生产Azure队列和其他msmq。Gof指的是这种产品关系作为一个"家庭"很重要注意,在这种情况下,族并不意味着类层次结构。
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    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();
        }
    }

    工厂法

  • 这里最重要的一点是要掌握是客户端。换句话说,客户机是一个子类,其父类定义factoryMethod()。这就是为什么我们这么说工厂方法是通过继承实现的。
  • 第二个关键点是记住工厂方法模式只不过是模板方法的专门化。模式。这两种模式具有相同的结构。他们只目的不同。工厂方法是创造性的(它建立但是模板方法是行为的(它计算某物)
  • 最后,要注意的第三点是,Creator(父级)类调用自己的factoryMethod()。如果我们移除父类中的anOperation(),只留下一个方法在后面,它不再是工厂方法模式。换言之,工厂方法不能用中少于两个的方法实现父类;其中一个必须调用另一个。
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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();
        }
    }

    杂项。&各种工厂模式(amp;D)

    请注意,尽管GOF定义了两种不同的工厂模式,但它们并不是现有的唯一工厂模式。它们甚至不一定是最常用的工厂模式。著名的第三个例子是Josh Bloch从有效Java中提取的静态工厂模式。头一设计模式书包括另一个模式,他们称为简单工厂。

    不要陷入这样的陷阱:假设每个工厂模式都必须与来自GOF的模式匹配。


    考虑这个例子以便于理解。

    电信公司提供什么?例如,宽带、电话线和手机,您需要创建一个应用程序来向客户提供他们的产品。

    一般来说,您在这里要做的是,创建产品,即宽带、电话线和移动设备,都是通过您的工厂方法来实现的,您知道这些产品的属性,这非常简单。

    现在,该公司想为他们的客户提供一系列产品,即宽带、电话线和移动设备,而现在,抽象工厂开始发挥作用了。

    也就是说,抽象工厂是负责创建自己产品的其他工厂的组成部分,抽象工厂知道如何将这些产品放在对自己职责更有意义的位置。

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

    请参阅下面的代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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.
        }
    }

    希望这有帮助。


    了解动机的差异:

    假设您正在构建一个工具,其中包含对象和对象之间相互关系的具体实现。由于您预见了对象中的变化,所以您已经通过将创建对象变化的职责分配给另一个对象(我们称之为抽象工厂)来创建了间接寻址。这个抽象发现了很大的好处,因为您预见到未来的扩展需要这些对象的变体。

    在这一思路中另一个相当有趣的动机是这样一个例子:来自整个团队的每一个或没有一个对象都会有相应的变体。根据某些条件,将使用任一变体,并且在每种情况下,所有对象都必须具有相同的变体。这可能有点违反直觉,因为我们通常认为——只要对象的变体遵循一个通用的统一契约(广义上的接口),具体的实现代码就永远不会中断。这里有趣的事实是,并非总是这样,尤其是当预期行为不能由编程契约建模时。

    一个简单的(借用gof的想法)是任何图形用户界面应用程序,比如说一个模拟MS或Mac或Fedora操作系统外观的虚拟监视器。例如,在这里,当窗口、按钮等所有小部件对象都有MS变体时,除了一个源自Mac变体的滚动条外,该工具的用途严重失败。

    这些案例构成了抽象工厂模式的基本需求。

    另一方面,假设您正在编写一个框架,这样许多人就可以使用您的框架构建各种工具(如上述示例中的工具)。从框架的概念来看,您不需要这样做,尽管您不能在逻辑中使用具体的对象。您更愿意在各种对象之间以及它们如何交互之间放置一些高级契约。虽然您(作为一个框架开发人员)仍然处于非常抽象的级别,但是工具的每个构建人员都必须遵循您的框架构造。然而,他们(工具构建者)可以自由决定要构建什么对象,以及他们创建的所有对象将如何交互。与前面的案例(抽象工厂模式)不同,在本例中,您(作为框架创建者)不需要使用具体的对象,而是可以停留在对象的契约级别。此外,与前面动机的第二部分不同,您或工具构建者从未遇到过将来自变体的对象混合在一起的情况。在这里,虽然框架代码仍然是合同级别的,但是每个工具生成器(根据案例本身的性质)都被限制使用它们自己的对象。在这种情况下,对象创建被委托给每个实现者,框架提供者只提供创建和返回对象的统一方法。这样的方法对于框架开发人员继续编写代码是不可避免的,并且有一个特殊的名字叫做工厂方法(底层模式的工厂方法模式)。

    注:

    • 如果您熟悉"模板方法",那么您将看到工厂方法通常是从模板方法调用的,以防与任何形式的框架相关的程序。相比之下,应用程序的模板方法往往是特定算法的简单实现和工厂方法的无效。
    • 此外,为了思想的完整性,使用框架(如上所述),当工具生成器在每个工厂方法中构建工具时,他/她可以进一步将责任委托给抽象工厂对象,而不是创建具体对象,前提是工具生成器预见具体对象的变化未来的扩展。

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    //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
        }
        ….
    }

  • My first question is about the abstract factory. Is its role to allow you to create families of concrete objects in (that can depend on what specific factory you use) rather than just a single concrete object?
  • 对。抽象工厂的目的是:

    Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

  • Does the abstract factory only return one very large object or many objects depending on what methods you call?
  • 理想情况下,它应该为每个客户机正在调用的方法返回一个对象。

  • My understanding is that the factory method pattern has a Creator interface that will make the ConcreteCreator be in charge of knowing which ConcreteProduct to instantiate. Is this what it means by using inheritance to handle object instantiation?
  • 对。工厂方法使用继承。

  • Abstract Factory pattern delegate the responsibility of object instantiation to another object via composition? What does this mean?
  • AbstractFactory定义了一个FactoryMethod,而ConcreteFactory负责构建一个混凝土产品。只需遵循本文中的代码示例。

    您可以在相关的SE文章中找到更多详细信息:

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

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


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


    要使其非常简单,具有最小的界面,请关注"//1":

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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.factory&abstractFactory机制必须使用继承(system.object->byte,float…);因此,如果在程序中有继承,那么factory(抽象工厂很可能不在那里)在设计2中就已经存在了。创建者(MyFactory)知道具体类型,所以将具体类型对象返回给调用者(Main);在抽象工厂中,返回类型将是一个接口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    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.要求:本田将创造"常规","运动",但英雄将创造"黑马","运动"和"滑板车"。2。为什么有两个接口?一种是制造商类型(IvehicleFactory),另一种是产品工厂类型(Ivehicle);另一种理解2个接口的方法是抽象工厂,即创建相关对象2。捕获是依维希勒工厂返回的子对象和依维希勒(而不是工厂中的具体对象);所以我得到父变量(依维希勒);然后我通过调用CreateSingleVehicle创建实际的具体类型,然后将父对象强制转换为实际的子对象。如果我执行RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");,会发生什么;您将得到applicationexception,这就是为什么我们需要通用抽象工厂,如果需要,我会解释。希望从初学者到中级观众都能有所帮助。


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

    工厂

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

    抽象工厂

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

    我在这里解释了工厂方法模式和抽象工厂模式,首先不使用它们解释问题,然后使用上述模式解决问题。https://github.com/vikramnaginini/design-patterns/tree/master网站


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

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

    工厂高层图和抽象工厂模式,

    diagram

    有关工厂方法的更多信息,请参阅本文。

    有关抽象工厂方法的更多信息,请参阅本文。


    上面的许多答案并没有提供抽象工厂和工厂方法模式之间的代码比较。下面是我尝试通过Java解释它的方法。希望它能帮助需要简单解释的人。

    As GoF aptly says : Abstract Factory provides an interface for creating families of related or dependent objects without specifying
    their concrete classes.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
            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();
                }

            }


    请允许我精确地说。大多数答案已经解释过了,并提供了图表和示例。所以我的铁锤只不过是一条直线。我自己的话是:"抽象工厂模式在多个工厂方法实现的抽象层上添加。表示抽象工厂包含或组合一个或多个工厂方法模式"


    任何时候我都喜欢抽象工厂而不是工厂方法。从上面的Tom Dalling的例子(很好的解释btw),我们可以看到抽象工厂更容易组合,因为我们需要做的就是将一个不同的工厂传递给构造函数(这里使用的是构造函数依赖注入)。但是工厂方法要求我们引入一个新的类(更多的东西需要管理)并使用子类。总是喜欢组合而不是继承。