开发者

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

I know there are many posts out there about the differences between these two patterns, but there are a few things that I cannot find.

From what I have been reading, I see that the factory method pattern allows you to define how to create a single concrete product but hiding the implementation from the client as they will see a generic product. 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? Does the abstract factory only return one very large object or many objects depending on what methods you call?

My final two questions are about a single quote that I cannot fully understand that I have seen in numerous places:

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.

My understand开发者_Go百科ing 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?

Now with regards to that quote, how exactly does the Abstract Factory pattern delegate the responsibility of object instantiation to another object via composition? What does this mean? It looks like the Abstract Factory pattern also uses inheritance to do the construction process as well in my eyes, but then again I am still learning about these patterns.

Any help especially with the last question, would be greatly appreciated.


The Difference Between The Two

The main difference between a "factory method" and an "abstract factory" is that the factory method is a method, and an abstract factory is an object. I think a lot of people get these two terms confused, and start using them interchangeably. I remember that I had a hard time finding exactly what the difference was when I learnt them.

Because the factory method is just a method, it can be overridden in a subclass, hence the second half of your quote:

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

The quote assumes that an object is calling its own factory method here. Therefore the only thing that could change the return value would be a subclass.

The abstract factory is an object that has multiple factory methods on it. Looking at the first half of your quote:

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

What they're saying is that there is an object A, who wants to make a Foo object. Instead of making the Foo object itself (e.g., with a factory method), it's going to get a different object (the abstract factory) to create the Foo object.

Code Examples

To show you the difference, here is a factory method in use:

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();
    }
}

And here is an abstract factory in use:

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


Abstract factory creates a base class with abstract methods defining methods for the objects that should be created. Each factory class which derives the base class can create their own implementation of each object type.

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

Factory method is just a simple method used to create objects in a class. It's usually added in the aggregate root (The Order class has a method called CreateOrderLine)

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

Abstract factory

In the example below we design an interface so that we can decouple queue creation from a messaging system and can therefore create implementations for different queue systems without having to change the code base.

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(/*....*/);
      }
}

Factory method

The problem in HTTP servers is that we always need an response for every request.

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

    IHttpResponse CreateResponse(int httpStatusCode);
}

Without the factory method, the HTTP server users (i.e. programmers) would be forced to use implementation specific classes which defeat the purpose of the IHttpRequest interface.

Therefore we introduce the factory method so that the creation of the response class also is abstracted away.

Summary

The difference is that the intended purpose of the class containing a factory method is not to create objects, while an abstract factory should only be used to create objects.

One should take care when using factory methods since it's easy to break the LSP (Liskov Substitution principle) when creating objects.


Difference between AbstractFactory and Factory design patterns are as follows:

  • Factory Method is used to create one product only but Abstract Factory is about creating families of related or dependent products.
  • Factory Method pattern exposes a method to the client for creating the object whereas in the case of Abstract Factory they expose a family of related objects which may consist of these Factory methods.
  • Factory Method pattern hides the construction of a single object whereas Abstract Factory hides the construction of a family of related objects. Abstract factories are usually implemented using (a set of) factory methods.
  • Abstract Factory pattern uses composition to delegate the responsibility of creating an object to another class while Factory Method design pattern uses inheritance and relies on a derived class or subclass to create an object.
  • The idea behind the Factory Method pattern is that it allows for the case where a client doesn't know what concrete classes it will be required to create at runtime, but just wants to get a class that will do the job while Abstract Factory pattern is best utilized when your system has to create multiple families of products or you want to provide a library of products without exposing the implementation details.!

Factory Method Pattern Implementation:

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

Abstract Factory Pattern Implementation:

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


The main difference between Abstract Factory and Factory Method is that Abstract Factory is implemented by Composition; but Factory Method is implemented by Inheritance.

Yes, you read that correctly: the main difference between these two patterns is the old composition vs inheritance debate.

UML diagrams can be found in the (GoF) book. I want to provide code examples, because I think combining the examples from the top two answers in this thread will give a better demonstration than either answer alone. Additionally, I have used terminology from the book in class and method names.

Abstract Factory

  1. The most important point to grasp here is that the abstract factory is injected into the client. This is why we say that Abstract Factory is implemented by Composition. Often, a dependency injection framework would perform that task; but a framework is not required for DI.
  2. The second critical point is that the concrete factories here are not Factory Method implementations! Example code for Factory Method is shown further below.
  3. And finally, the third point to note is the relationship between the products: in this case the outbound and reply queues. One concrete factory produces Azure queues, the other MSMQ. The GoF refers to this product relationship as a "family" and it's important to be aware that family in this case does not mean class hierarchy.
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();
    }
}

Factory Method

  1. The most important point to grasp here is that the ConcreteCreator is the client. In other words, the client is a subclass whose parent defines the factoryMethod(). This is why we say that Factory Method is implemented by Inheritance.
  2. The second critical point is to remember that the Factory Method Pattern is nothing more than a specialization of the Template Method Pattern. The two patterns share an identical structure. They only differ in purpose. Factory Method is creational (it builds something) whereas Template Method is behavioral (it computes something).
  3. And finally, the third point to note is that the Creator (parent) class invokes its own factoryMethod(). If we remove anOperation() from the parent class, leaving only a single method behind, it is no longer the Factory Method pattern. In other words, Factory Method cannot be implemented with less than two methods in the parent class; and one must invoke the other.
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();
    }
}

Misc. & Sundry Factory Patterns

Be aware that although the GoF define two different Factory patterns, these are not the only Factory patterns in existence. They are not even necessarily the most commonly used Factory patterns. A famous third example is Josh Bloch's Static Factory Pattern from Effective Java. The Head First Design Patterns book includes yet another pattern they call Simple Factory.

Don't fall into the trap of assuming every Factory pattern must match one from the GoF.


Abstract Factory is an interface for creating related products, but Factory Method is only one method. Abstract Factory can be implemented by multiple Factory Methods.

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


Consider this example for easy understanding.

What does telecommunication companies provide? Broadband, phone line and mobile for instance and you're asked to create an application to offer their products to their customers.

Generally what you'd do here is, creating the products i.e broadband, phone line and mobile are through your Factory Method where you know what properties you have for those products and it's pretty straightforward.

Now, the company wants to offer their customer a bundle of their products i.e broadband, phone line, and mobile altogether, and here comes the Abstract Factory to play.

Abstract Factory is, in other words, are the composition of other factories who are responsible for creating their own products and Abstract Factory knows how to place these products in more meaningful in respect of its own responsibilities.

In this case, the BundleFactory is the Abstract Factory, BroadbandFactory, PhonelineFactory and MobileFactory are the Factory. To simplify more, these Factories will have Factory Method to initialise the individual products.

Se the code sample below:

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.
    }
}

Hope this helps.


Factory Method relies on inheritance: Object creation is delegated to subclasses, which implement the factory method to create objects.

Abstract Factory relies on object composition: object creation is implemented in methods exposed in the factory interface.

High level diagram of Factory and Abstract factory pattern,

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

For more information about the Factory method, refer this article.

For more information about Abstract factory method, refer this article.


Real Life Example. (Easy to remember)

Factory

Imagine you are constructing a house and you approach a carpenter for a door. You give the measurement for the door and your requirements, and he will construct a door for you. In this case, the carpenter is a factory of doors. Your specifications are inputs for the factory, and the door is the output or product from the factory.

Abstract Factory

Now, consider the same example of the door. You can go to a carpenter, or you can go to a plastic door shop or a PVC shop. All of them are door factories. Based on the situation, you decide what kind of factory you need to approach. This is like an Abstract Factory.

I have explained here both Factory method pattern and abstract factory pattern beginning with not using them explaining issues and then solving issues by using the above patterns https://github.com/vikramnagineni/Design-Patterns/tree/master


There are quite a few definitions out there. Basically, the three common way of describing factory pattern are

  1. Simple Factory

Simple object creation method/class based on a condition.

  1. Factory Method

The Factory Method design pattern using subclasses to provide the implementation.

  1. Abstract Factory

The Abstract Factory design pattern producing families of related or dependent objects without specifying their concrete classes.

The below link was very useful - Factory Comparison - refactoring.guru


Understand the differences in the motivations:

Suppose you’re building a tool where you’ve objects and a concrete implementation of the interrelations of the objects. Since you foresee variations in the objects, you’ve created an indirection by assigning the responsibility of creating variants of the objects to another object (we call it abstract factory). This abstraction finds strong benefit since you foresee future extensions needing variants of those objects.

Another rather intriguing motivation in this line of thoughts is a case where every-or-none of the objects from the whole group will have a corresponding variant. Based on some conditions, either of the variants will be used and in each case all objects must be of same variant. This might be a bit counter intuitive to understand as we often tend think that - as long as the variants of an object follow a common uniform contract (interface in broader sense), the concrete implementation code should never break. The intriguing fact here is that, not always this is true especially when expected behavior cannot be modeled by a programming contract.

A simple (borrowing the idea from GoF) is any GUI applications say a virtual monitor that emulates look-an-feel of MS or Mac or Fedora OS’s. Here, for example, when all widget objects such as window, button, etc. have MS variant except a scroll-bar that is derived from MAC variant, the purpose of the tool fails badly.

These above cases form the fundamental need of Abstract Factory Pattern.

On the other hand, imagine you’re writing a framework so that many people can built various tools (such as the one in above examples) using your framework. By the very idea of a framework, you don’t need to, albeit you could not use concrete objects in your logic. You rather put some high level contracts between various objects and how they interact. While you (as a framework developer) remain at a very abstract level, each builders of the tool is forced to follow your framework-constructs. However, they (the tool builders) have the freedom to decide what object to be built and how all the objects they create will interact. Unlike the previous case (of Abstract Factory Pattern), you (as framework creator) don’t need to work with concrete objects in this case; and rather can stay at the contract level of the objects. Furthermore, unlike the second part of the previous motivations, you or the tool-builders never have the situations of mixing objects from variants. Here, while framework code remains at contract level, every tool-builder is restricted (by the nature of the case itself) to using their own objects. Object creations in this case is delegated to each implementer and framework providers just provide uniform methods for creating and returning objects. Such methods are inevitable for framework developer to proceed with their code and has a special name called Factory method (Factory Method Pattern for the underlying pattern).

Few Notes:

  • If you’re familiar with ‘template method’, then you’d see that factory methods are often invoked from template methods in case of programs pertaining to any form of framework. By contrast, template methods of application-programs are often simple implementation of specific algorithm and void of factory-methods.
  • Furthermore, for the completeness of the thoughts, using the framework (mentioned above), when a tool-builder is building a tool, inside each factory method, instead of creating a concrete object, he/she may further delegate the responsibility to an abstract-factory object, provided the tool-builder foresees variations of the concrete objects for future extensions.

Sample Code:

//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
    }
    ….
}


  1. 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?

Yes. The intent of Abstract Factory is:

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


  1. Does the abstract factory only return one very large object or many objects depending on what methods you call?

Ideally it should return one object per the method client is invoking.

  1. 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?

Yes. Factory method uses inheritance.

  1. Abstract Factory pattern delegate the responsibility of object instantiation to another object via composition? What does this mean?

AbstractFactory defines a FactoryMethod and ConcreteFactory is responsible for building a ConcreteProduct. Just follow through the code example in this article.

You can find more details in related SE posts:

What is the basic difference between the Factory and Abstract Factory Patterns?

Design Patterns: Factory vs Factory method vs Abstract Factory


Let us put it clear that most of the time in production code, we use abstract factory pattern because class A is programmed with interface B. And A needs to create instances of B. So A has to have a factory object to produce instances of B. So A is not dependent on any concrete instance of B. Hope it helps.


Factory Design Pattern

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

Factory

Use case: instantiate one object of generation 2

It is a Creational pattern which allows you to create generation 2 in a simple place. It conforms SRP and OCP - all changes are made in a single class.

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);
    }
}

Factory method

Use case: instantiate one object of generation 3

Helps to work with next generation of family members. Every painter has his own style like Impressionism, Surrealism... Factory Method uses abstract Creator as Factory(abstract method) and Concrete Creators are realizations of this method

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);
    }
}

Abstract Factory

Use case: instantiate all objects of generation 3

Factory is a part of abstract Factory and realisations in 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;
    }
}


To make it very simple with minimum interface & please focus "//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;
        }
    }

Here important points: 1. Factory & AbstractFactory mechanisms must use inheritance (System.Object-> byte, float ...); so if you have inheritance in program then Factory(Abstract Factory would not be there most probably) is already there by design 2. Creator (MyFactory) knows about concrete type so returns concrete type object to caller(Main); In abstract factory return type would be an Interface.

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();
    }
}

Important points: 1. Requirement: Honda would create "Regular", "Sports" but Hero would create "DarkHorse", "Sports" and "Scooty". 2. why two interfaces? One for manufacturer type(IVehicleFactory) and another for product factory(IVehicle); other way to understand 2 interfaces is abstract factory is all about creating related objects 2. The catch is the IVehicleFactory's children returning and IVehicle(instead of concrete in factory); so I get parent variable(IVehicle); then I create actual concrete type by calling CreateSingleVehicle and then casting parent object to actual child object. What would happen if I do RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; you will get ApplicationException and that's why we need generic abstract factory which I would explain if required. Hope it helps from beginner to intermediate audience.


A) Factory Method pattern

The Factory Method is a creational design pattern that provides an interface for creating objects but allows subclasses to alter the type of an object that will be created.

If you have a creation method in base class and subclasses that extend it, you might be looking at the factory method.

B)Abstract Factory pattern

The Abstract Factory is a creational design pattern that allows producing families of related or dependent objects without specifying their concrete classes.

What are the "families of objects"? For instance, take this set of classes: Transport + Engine + Controls. There are might be several variants of these:

1- Car + CombustionEngine + SteeringWheel

2- Plane + JetEngine + Yoke

If your program doesn’t operate with product families, then you don’t need an abstract factory.

And again, a lot of people mix-up the abstract factory pattern with a simple factory class declared as abstract. Don’t do that!

REF: https://refactoring.guru/design-patterns/factory-comparison


In my estimation the answer given by @TomDalling is indeed correct (for what it's worth), however there still seems to be a lot of confusion in the comments.

What I've done here is create some slightly atypical examples of the two patterns and tried to make them appear at first glance quite similar. This will help to pinpoint the crtical differences that separate them.

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

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

If you're completely new to the patterns these examples are propably not the best place to start.

Factory Method

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

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();
}

Why is there a Creator and a Client?

Why not? The FactoryMethod can be used with both, but it will be the type of Creator that determines the specific product created.

Why isn't createProductB abstract in Creator?

A default implementation can be provided, subclasses can still override the method to provide their own implementation.

I thought factory methods only create one product?

Each method does return just one product, but the creator can use multiple factory methods, they just aren't necessarily related in any particular way.

Abstract Factory

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

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();
}

Wait! Your AbstractFactory isn't, well... er Abstract

That's okay, we're still providing an interface. The return types on the create methods are super-types of the products we want to make.

Holy Smoke Batman! Factory2 doesn't override createProductA(), what happened to "families of products"?

There's nothing in the pattern that says an object can't belong to more than one family (although your use case might prohibit it). Each concrete factory is responsible for deciding which products are allowed to be created together.

That can't be right, the Client isn't using dependency injection

You've got to decide what your concrete classes will be somewhere, the Client is still written to the AbstractFactory interface.

The confusion here is that people conflate composition with dependency injection. The Client HAS-A AbstractFactory regardless of how it got it. Contrast with the IS-A relationship, Client and AbstractFactory have no inheritance between them.

Key Differences

  • Abstract Factory is always about families of objects
  • Factory Method is just a method that allows subclasses to specify the type of concrete object
  • Abstract Factory provides an interface to a Client and is separate from where the products are used, the Factory Method could be used by the Creator itself or exposed to a Client.

Summary

The purpose of a factory is to provide a objects, either to a client or itself.

A creator has its own responsibilities and may need to use objects or pass them to a client

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. - GoF

An abstract factory only:

Provide[s] an interface for creating families of related or dependent objects without specifying their concrete classes. - GoF


PlantUML code if you want to play with the diagrams:

@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


I would favor Abstract Factory over Factory Method anytime. From Tom Dalling's example (great explanation btw) above, we can see that Abstract Factory is more composable in that all we need to do is passing a different Factory to the constructor (constructor dependency injection in use here). But Factory Method requires us to introduce a new class (more things to manage) and use subclassing. Always prefer composition over inheritance.


Abstract Factory: A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes. Abstract Factory Example

Factory: It provides a way to delegate the instantiation logic to child classes. Factory Pattern Example


Allow me to put it precisely. Most of the answers have already explained, provided diagrams and examples as well.

So my answer would just be a one-liner. My own words: “An abstract factory pattern adds on the abstract layer over multiple factory method implementations. It means an abstract factory contains or composite one or more than one factory method pattern”


A lot of the previous answers do not provide code comparisons between Abstract Factory and Factory Method pattern. The following is my attempt at explaining it via Java. I hope it helps someone in need of a simple explanation.

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

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();
    }

}


My conclusion: there is no difference. Why? Because I cannot see any justification to equip objects other than factories with factory methods - otherwise you get a violation of the separation of responsibility principle. In addition, I cannot see any difference between a factory with a single factory method and a factory with multiple factory methods: both create "families of related objects" unless anyone can prove that a single-family-member family is not a family. Or a collection that contains a single item is not a collection.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜