`
阿尔萨斯
  • 浏览: 4170695 次
社区版块
存档分类
最新评论

Design Pattern - Abstract Factory (C#)

 
阅读更多

Definition

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

UML Class Diagram

Participants

The classes and/or objects participating in this pattern are:

  • AbstractFactory(ContinentFactory)
    • Declares an interface for operations that create abstract products
  • ConcreteFactory (AfricaFactory, AmericaFactory)
    • Implements the operations to create concrete product objects
  • AbstractProduct (Herbivore, Carnivore)
    • Declares an interface for a type of product object
  • Product(Wildebeest, Lion, Bison, Wolf)
    • Defines a product object to be created by the corresponding concrete factory
    • Implements the AbstractProduct interface
  • Client(AnimalWorld)
    • Uses interfaces declared by AbstractFactory and AbstractProduct classes

Sample Code in C#


This structural code demonstrates the Abstract Factory pattern creating parallel hierarchies of objects. Object creation has been abstracted and there is no need for hard-coded class names in the client code.

// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Chimomo's Company" file="Program.cs">
// Respect the work.
// </copyright>
// <summary>
// Structural Abstract Factory Design Pattern.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace CSharpLearning
{
    using System;

    /// <summary>
    /// Startup class for Structural Abstract Factory Design Pattern.
    /// </summary>
    internal static class MainApp
    {
        #region Public Methods and Operators

        /// <summary>
        /// Entry point into console application.
        /// </summary>
        public static void Main()
        {
            // Abstract factory #1
            AbstractFactory factory1 = new ConcreteFactory1();
            var client1 = new Client(factory1);
            client1.Run();

            // Abstract factory #2
            AbstractFactory factory2 = new ConcreteFactory2();
            var client2 = new Client(factory2);
            client2.Run();
        }

        #endregion
    }

    /// <summary>
    /// The 'AbstractFactory' abstract class
    /// </summary>
    internal abstract class AbstractFactory
    {
        #region Public Methods and Operators

        /// <summary>
        /// The create product a.
        /// </summary>
        /// <returns>
        /// The <see cref="AbstractProductA"/>.
        /// </returns>
        public abstract AbstractProductA CreateProductA();

        /// <summary>
        /// The create product b.
        /// </summary>
        /// <returns>
        /// The <see cref="AbstractProductB"/>.
        /// </returns>
        public abstract AbstractProductB CreateProductB();

        #endregion
    }

    /// <summary>
    /// The 'ConcreteFactory1' class
    /// </summary>
    internal class ConcreteFactory1 : AbstractFactory
    {
        #region Public Methods and Operators

        /// <summary>
        /// The create product a.
        /// </summary>
        /// <returns>
        /// The <see cref="AbstractProductA"/>.
        /// </returns>
        public override AbstractProductA CreateProductA()
        {
            return new ProductA1();
        }

        /// <summary>
        /// The create product b.
        /// </summary>
        /// <returns>
        /// The <see cref="AbstractProductB"/>.
        /// </returns>
        public override AbstractProductB CreateProductB()
        {
            return new ProductB1();
        }

        #endregion
    }

    /// <summary>
    /// The 'ConcreteFactory2' class
    /// </summary>
    internal class ConcreteFactory2 : AbstractFactory
    {
        #region Public Methods and Operators

        /// <summary>
        /// The create product a.
        /// </summary>
        /// <returns>
        /// The <see cref="AbstractProductA"/>.
        /// </returns>
        public override AbstractProductA CreateProductA()
        {
            return new ProductA2();
        }

        /// <summary>
        /// The create product b.
        /// </summary>
        /// <returns>
        /// The <see cref="AbstractProductB"/>.
        /// </returns>
        public override AbstractProductB CreateProductB()
        {
            return new ProductB2();
        }

        #endregion
    }

    /// <summary>
    /// The 'AbstractProductA' abstract class
    /// </summary>
    internal abstract class AbstractProductA
    {
    }

    /// <summary>
    /// The 'AbstractProductB' abstract class
    /// </summary>
    internal abstract class AbstractProductB
    {
        #region Public Methods and Operators

        /// <summary>
        /// The interact.
        /// </summary>
        /// <param name="a">
        /// The a.
        /// </param>
        public abstract void Interact(AbstractProductA a);

        #endregion
    }

    /// <summary>
    /// The 'ProductA1' class
    /// </summary>
    internal class ProductA1 : AbstractProductA
    {
    }

    /// <summary>
    /// The 'ProductB1' class
    /// </summary>
    internal class ProductB1 : AbstractProductB
    {
        #region Public Methods and Operators

        /// <summary>
        /// The interact.
        /// </summary>
        /// <param name="a">
        /// The a.
        /// </param>
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
        }

        #endregion
    }

    /// <summary>
    /// The 'ProductA2' class
    /// </summary>
    internal class ProductA2 : AbstractProductA
    {
    }

    /// <summary>
    /// The 'ProductB2' class
    /// </summary>
    internal class ProductB2 : AbstractProductB
    {
        #region Public Methods and Operators

        /// <summary>
        /// The interact.
        /// </summary>
        /// <param name="a">
        /// The a.
        /// </param>
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
        }

        #endregion
    }

    /// <summary>
    /// The 'Client' class. Interaction environment for the products.
    /// </summary>
    internal class Client
    {
        #region Fields

        /// <summary>
        /// The abstract product a.
        /// </summary>
        private AbstractProductA abstractProductA;

        /// <summary>
        /// The abstract product b.
        /// </summary>
        private AbstractProductB abstractProductB;

        #endregion

        // Constructor
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Client"/> class.
        /// </summary>
        /// <param name="factory">
        /// The factory.
        /// </param>
        public Client(AbstractFactory factory)
        {
            this.abstractProductA = factory.CreateProductA();
            this.abstractProductB = factory.CreateProductB();
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The run.
        /// </summary>
        public void Run()
        {
            this.abstractProductB.Interact(this.abstractProductA);
        }

        #endregion
    }
}

// Output:
/*
ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2
*/


This real-world code demonstrates the creation of different animal worlds for a computer game using different factories. Although the animals created by the Continent factories are different, the interactions among the animals remain the same.

// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Chimomo's Company" file="Program.cs">
// Respect the work.
// </copyright>
// <summary>
// Real-World Abstract Factory Design Pattern.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace CSharpLearning
{
    using System;

    /// <summary>
    /// Startup class for Real-World Abstract Factory Design Pattern.
    /// </summary>
    internal static class MainApp
    {
        #region Public Methods and Operators

        /// <summary>
        /// Entry point into console application.
        /// </summary>
        public static void Main()
        {
            // Create and run the African animal world
            ContinentFactory africa = new AfricaFactory();
            var world = new AnimalWorld(africa);
            world.RunFoodChain();

            // Create and run the American animal world
            ContinentFactory america = new AmericaFactory();
            world = new AnimalWorld(america);
            world.RunFoodChain();
        }

        #endregion
    }

    /// <summary>
    /// The 'AbstractFactory' abstract class
    /// </summary>
    internal abstract class ContinentFactory
    {
        #region Public Methods and Operators

        /// <summary>
        /// The create carnivore.
        /// </summary>
        /// <returns>
        /// The <see cref="Carnivore"/>.
        /// </returns>
        public abstract Carnivore CreateCarnivore();

        /// <summary>
        /// The create herbivore.
        /// </summary>
        /// <returns>
        /// The <see cref="Herbivore"/>.
        /// </returns>
        public abstract Herbivore CreateHerbivore();

        #endregion
    }

    /// <summary>
    /// The 'ConcreteFactory1' class
    /// </summary>
    internal class AfricaFactory : ContinentFactory
    {
        #region Public Methods and Operators

        /// <summary>
        /// The create carnivore.
        /// </summary>
        /// <returns>
        /// The <see cref="Carnivore"/>.
        /// </returns>
        public override Carnivore CreateCarnivore()
        {
            return new Lion();
        }

        /// <summary>
        /// The create herbivore.
        /// </summary>
        /// <returns>
        /// The <see cref="Herbivore"/>.
        /// </returns>
        public override Herbivore CreateHerbivore()
        {
            return new Wildebeest();
        }

        #endregion
    }

    /// <summary>
    /// The 'ConcreteFactory2' class
    /// </summary>
    internal class AmericaFactory : ContinentFactory
    {
        #region Public Methods and Operators

        /// <summary>
        /// The create carnivore.
        /// </summary>
        /// <returns>
        /// The <see cref="Carnivore"/>.
        /// </returns>
        public override Carnivore CreateCarnivore()
        {
            return new Wolf();
        }

        /// <summary>
        /// The create herbivore.
        /// </summary>
        /// <returns>
        /// The <see cref="Herbivore"/>.
        /// </returns>
        public override Herbivore CreateHerbivore()
        {
            return new Bison();
        }

        #endregion
    }

    /// <summary>
    /// The 'AbstractProductA' abstract class
    /// </summary>
    internal abstract class Herbivore
    {
    }

    /// <summary>
    /// The 'AbstractProductB' abstract class
    /// </summary>
    internal abstract class Carnivore
    {
        #region Public Methods and Operators

        /// <summary>
        /// The eat.
        /// </summary>
        /// <param name="h">
        /// The h.
        /// </param>
        public abstract void Eat(Herbivore h);

        #endregion
    }

    /// <summary>
    /// The 'ProductA1' class
    /// </summary>
    internal class Wildebeest : Herbivore
    {
    }

    /// <summary>
    /// The 'ProductB1' class
    /// </summary>
    internal class Lion : Carnivore
    {
        #region Public Methods and Operators

        /// <summary>
        /// The eat.
        /// </summary>
        /// <param name="h">
        /// The h.
        /// </param>
        public override void Eat(Herbivore h)
        {
            // Eat Wildebeest
            Console.WriteLine(this.GetType().Name + " eats " + h.GetType().Name);
        }

        #endregion
    }

    /// <summary>
    /// The 'ProductA2' class
    /// </summary>
    internal class Bison : Herbivore
    {
    }

    /// <summary>
    /// The 'ProductB2' class
    /// </summary>
    internal class Wolf : Carnivore
    {
        #region Public Methods and Operators

        /// <summary>
        /// The eat.
        /// </summary>
        /// <param name="h">
        /// The h.
        /// </param>
        public override void Eat(Herbivore h)
        {
            // Eat Bison
            Console.WriteLine(this.GetType().Name + " eats " + h.GetType().Name);
        }

        #endregion
    }

    /// <summary>
    /// The 'Client' class
    /// </summary>
    internal class AnimalWorld
    {
        #region Fields

        /// <summary>
        /// The carnivore.
        /// </summary>
        private Carnivore carnivore;

        /// <summary>
        /// The herbivore.
        /// </summary>
        private Herbivore herbivore;

        #endregion

        // Constructor
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="AnimalWorld"/> class.
        /// </summary>
        /// <param name="factory">
        /// The factory.
        /// </param>
        public AnimalWorld(ContinentFactory factory)
        {
            this.carnivore = factory.CreateCarnivore();
            this.herbivore = factory.CreateHerbivore();
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The run food chain.
        /// </summary>
        public void RunFoodChain()
        {
            this.carnivore.Eat(this.herbivore);
        }

        #endregion
    }
}

// Output:
/*
Lion eats Wildebeest
Wolf eats Bison
*/
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics