Object Oriented Programming Patterns for Geeks

The Abstract Factory

 

namespace ooppatterns
{
    using System;

    internal class Program
    {
        private static void Main( string[] args )
        {
            // Abstract factory #1 
            IAbstractFactory factory1 = new ConcreteFactoryA();
            Client c1 = new Client( factory1 );
            c1.UseProducts();

            // Abstract factory #2 
            IAbstractFactory factory2 = new ConcreteFactoryB();
            Client c2 = new Client( factory2 );
            c2.UseProducts();

            Console.ReadLine();
        }
    }

    // the "AbstractFactory" which in .NET is usually an Interface
    internal interface IAbstractFactory
    {
        IProductA CreateProductA();

        IProductB CreateProductB();
    }

    // "AbstractProduct"'s which in .NET is usually an Interface
    internal interface IProductA
    {
        void DoSomething( IProductB a );
    }

    internal interface IProductB
    {
        void Interact( IProductA a );
    }

    // The concrete factory A
    internal class ConcreteFactoryA : IAbstractFactory
    {
        public IProductA CreateProductA()
        {
            return new ProductA1();
        }

        public IProductB CreateProductB()
        {
            return new ProductB1();
        }
    }

    // The concrete factory B
    internal class ConcreteFactoryB : IAbstractFactory
    {
        public IProductA CreateProductA()
        {
            return new ProductA2();
        }

        public IProductB CreateProductB()
        {
            return new ProductB2();
        }
    }

    // The factories products...
    internal class ProductA1 : IProductA
    {
        public void DoSomething( IProductB a )
        {
            Console.WriteLine( "{0} Does Something with {1}", 
                this.GetType().Name, a.GetType().Name );
        }
    }

    internal class ProductB1 : IProductB
    {
        public void Interact( IProductA a )
        {
            Console.WriteLine( "{0} interacts with {1}", 
                this.GetType().Name, a.GetType().Name );
        }
    }

    internal class ProductA2 : IProductA
    {
        public void DoSomething( IProductB a )
        {
            Console.WriteLine( "{0} Does Something with {1}", 
                this.GetType().Name, a.GetType().Name );
        }
    }

    internal class ProductB2 : IProductB
    {
        public void Interact( IProductA a )
        {
            Console.WriteLine( "{0} interacts with {1}", 
                this.GetType().Name, a.GetType().Name );
        }
    }

    // the client that consumes the products
    internal class Client
    {
        private IProductA _ProductA;
        private IProductB _ProductB;

        // Constructor 
        public Client( IAbstractFactory factory )
        {
            this._ProductB = factory.CreateProductB();
            this._ProductA = factory.CreateProductA();
        }

        public void UseProducts()
        {
            this._ProductA.DoSomething( this._ProductB );
            this._ProductB.Interact( this._ProductA );
        }
    }
}