Abstract factory pattern [C_version]

In order to highlight the characteristics of the design pattern as much as possible, the sample code uses minimal code. Avoid other code interfering with understanding design patterns as much as possible

Definition:

Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their specific classes.
In short, it is the abstract factory model, which enables specific factories to create multiple products at the same time. For example, in the following example code, the computer factory has the ability to produce displays, as well as the ability to produce hosts.

Structural Map (quoted from) Mr. Liu Wei's blog)

Code:

Product Code

  • Product-Display

    /// <summary>
    /// abstract products
    /// Abstract Display
    /// </summary>
    interface IDisplay
    {
        void Show();
    }
    /// <summary>
    /// Specific products
    /// Apple Display
    /// </summary>
    class AppleDisplay : IDisplay
    {
        public void Show()
        {
            Console.WriteLine("The Apple monitor is working properly.");
        }
    }
    /// <summary>
    /// Specific products
    /// Dell Display
    /// </summary>
    class DellDisplay : IDisplay
    {
        public void Show()
        {
            Console.WriteLine("The Dell monitor is working properly.");
        }
    }
  • Product-Host

    /// <summary>
    /// abstract products
    /// abstract host
    /// </summary>
    interface IMainframe
    {
        void Open();
    }
    /// <summary>
    /// Specific products
    /// Apple Host
    /// </summary>
    class AppleMainframe : IMainframe
    {
        public void Open()
        {
            Console.WriteLine("The Apple mainframe booted successfully.");
        }
    }
    /// <summary>
    /// Specific products
    /// Dell Host
    /// </summary>
    class DellMainframe : IMainframe
    {
        public void Open()
        {
            Console.WriteLine("Dell mainframe boot successfully.");
        }
    }

If we use the common factory model, then each product should have its corresponding factory class, which will lead to the situation, we need to provide both "display factory class" and "host factory class". After adding keyboard, mouse and other products, there will be more corresponding factory class. This will undoubtedly lead to too many factories in the project, which will increase the complexity of the project to a certain extent.

At this point, the abstract factory model comes in handy!

Factory code

    /// <summary>
    /// abstract factory
    /// Computer Factory
    /// </summary>
    interface IComputerFactory
    {
        /// <summary>
        /// Produce a monitor
        /// </summary>
        IDisplay ProduceADisplay();
    
        /// <summary>
        /// Produce a mainframe
        /// </summary>
        IMainframe ProduceAMainframe();
    }
    /// <summary>
    /// Specific factories
    /// Apple Computer Factory
    /// </summary>
    class AppleComputerFactory : IComputerFactory
    {
        public IDisplay ProduceADisplay()
        {
            return new AppleDisplay();
        }
    
        public IMainframe ProduceAMainframe()
        {
            return new AppleMainframe();
        }
    }
    /// <summary>
    /// Specific factories
    /// Dell Computer Factory
    /// </summary>
    class DellComputerFactory : IComputerFactory
    {
        public IDisplay ProduceADisplay()
        {
            return new DellDisplay();
        }
    
        public IMainframe ProduceAMainframe()
        {
            return new DellMainframe();
        }
    }

At this time, every computer manufacturer has its own independent factory. Customers who want a computer need only find a designated manufacturer to customize it. Of course, in fact, people usually don't go to the manufacturer directly when they buy a computer. This is just a metaphor. P

See Client Code

    class Program
    {
        static void Main(string[] args)
        {
            // Suppose I want an Apple computer at this point.
            // Creating Apple Computer Factory
            var factory = new AppleComputerFactory();
    
            // Produce monitors and test for conformity
            var display = factory.ProduceADisplay();
            display.Show();
    
            // Produce the main engine and test whether the product is qualified.
            var mainframe = factory.ProduceAMainframe();
            mainframe.Open();
    
            // Finished
            Console.WriteLine("Computer production is completed and distribution is under way.ยทยทยท");
        }
    }

Above.

The output after operation is as follows:

Supplementary discussion:

Many people say that if you expand a specific product in the later period (for example, there are only two brands of computers, Apple and Dell, and Huawei Display and Huawei host), it is very simple to add a specific factory at most. But if a product is added (for example, there are only monitors and hosts now, and peripherals such as keyboards may be added later), it will be very difficult to expand, because the existing Abstract factories need to be changed in order to expand.
Once the existing Abstract factories have been changed (for example, the method of producing keyboards has been added), all the specific factories that inherited them need to be changed synchronously (even though some factories have not planned to sell keyboards from the beginning to the end, but they also need to be transformed along with the abstract factories). So calculate, change and Not small.

But what I have to say is that I don't have to change the existing Abstract factory. I can add new abstract factories.

The code is as follows:

    /// <summary>
    /// abstract factory
    /// Computer factory with keyboard attached
    /// </summary>
    abstract class IComputerFactory_Keyboard : IComputerFactory
    {
        /// <summary>
        /// Reference to holding old factories
        /// </summary>
        protected abstract IComputerFactory OldComputerFactory { get; }

        /// <summary>
        /// Production of displays through old factories
        /// </summary>
        public IDisplay ProduceADisplay()
        {
            return OldComputerFactory.ProduceADisplay();
        }

        /// <summary>
        /// Produce a keyboard
        /// </summary>
        public abstract IKeyboard ProduceAKeyboard();

        /// <summary>
        /// Making Host Machine through Old Factory
        /// </summary>
        public IMainframe ProduceAMainframe()
        {
            return OldComputerFactory.ProduceAMainframe();
        }
    }

A factory with a new keyboard attached

    /// <summary>
    /// Specific factories
    /// Dell's New Factory - Buy Computers for Keyboards
    /// </summary>
    class DellComputerFactory_Keyboard : IComputerFactory_Keyboard
    {
        private readonly DellComputerFactory ComputerFactory = new DellComputerFactory();
        protected override IComputerFactory OldComputerFactory
        {
            get
            {
                return ComputerFactory;
            }
        }

        public override IKeyboard ProduceAKeyboard()
        {
            return new DellKeyboard();
        }
    }

In this way, the designated manufacturer can produce keyboards without changing the original factory.
PS: C# can also add some additional production capacity to a specified factory by extending the method.

Keywords: C#

Added by phpform08 on Wed, 14 Aug 2019 10:04:27 +0300