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

后端 未结 17 1176
醉话见心
醉话见心 2020-11-22 01:57

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,

相关标签:
17条回答
  • 2020-11-22 02:37

    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.

    0 讨论(0)
  • 2020-11-22 02:38

    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,

    diagram

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

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

    0 讨论(0)
  • 2020-11-22 02:39

    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.

    0 讨论(0)
  • 2020-11-22 02:40

    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”

    0 讨论(0)
  • 2020-11-22 02:41

    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
        }
        ….
    }
    
    0 讨论(0)
  • 2020-11-22 02:42

    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

    0 讨论(0)
提交回复
热议问题