Showing posts with label Design Pattern. Show all posts
Showing posts with label Design Pattern. Show all posts

Saturday, July 22, 2023

Mediator Design Pattern


Mediator is an object that mediates between other objects to allow communication between them. Without mediator these objects will have to communicate directly. Let there be Sales and Marketing teams which want to communicate. They can send message from one to another using Send method.
void Send(string to, string from, string message);
Mediator design pattern is useful when multiple services are consumed by client classes in a uniform way.
We see the below example which is without Mediator Design Pattern. It will be converted into Mediator Design Pattern.
CASE1. Without Mediator Design Pattern
Create a console application in Visual Studio. Add a class file named as Team.cs Write the following code in it.
using System;

namespace MediatorDesignPattern
{
    public class Sales
    {
        public string Name { get; set; }
        public void Send(string to, string from, string message)
        {
            Console.WriteLine($"{message} sent from {from} to {to}");
        }
    }

    public class Marketing
    {
        public string Name { get; set; }
        public void Send(string to, string from, string message)
        {
            Console.WriteLine($"{message} sent from {from} to {to}");
        }
    }
}

In Program.cs, create the objects of the Sales and Marketing and invoke their Send methods.

namespace MediatorDesignPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Sales t1 = new Sales();
            Marketing t2 = new Marketing();
            t1.Name = "Sales";
            t2.Name = "Marketing";
            t1.Send(t1.Name, t2.Name,"MessageX");
            t2.Send(t2.Name, t1.Name,"MessageY");
        }
    }
}

Run the app. We get the following message.
MessageX sent from Marketing to Sales
MessageY sent from Sales to Marketing

Next, update the code in Team.cs file as given below. Club the Sales and Marketing classes into Team class. The Team is abstract class which is inherited by them.

using System;

namespace MediatorDesignPattern
{
    public abstract class Team
    {
        public abstract string Name { get; set; }
        public abstract void Send(string to, string from, string message);
    }
    public class Sales : Team
    {
        public override string Name { get; set; }
        public override void Send(string to, string from, string message)
        {
            Console.WriteLine($"{message} sent from {from} to {to}");
        }
    }

    public class Marketing : Team
    {
        public override string Name { get; set; }
        public override void Send(string to, string from, string message)
        {
            Console.WriteLine($"This message '{ message}' sent from {from} to {to}");
        }
    }
}
Program.cs is as before.
namespace MediatorDesignPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Sales t1 = new Sales();
            Marketing t2 = new Marketing();
            t1.Name = "Sales";
            t2.Name = "Marketing";
            t1.Send(t1.Name, t2.Name,"MessageX");
            t2.Send(t2.Name, t1.Name,"MessageY");
        }
    }
}

Run the app. We get the following message as before.
MessageX sent from Marketing to Sales
MessageY sent from Sales to Marketing

IMPORTANT: Here both Sales and Marketing teams are using their own Send method ( as they are overriding the abstract Send method in their own way)
But it is possible that there will be a mediator interface with Send method which is implemented uniformly by a mediator class. This class is used by both Sales and Marketing teams. Now, Send method is part of mediator and both Sales and Marketing use it. For this purpose, we create an interface named as IMediatorTeam which will be implemented by MediatorTeam class. Look at the following further updated code.
CASE2. With Mediator Design Pattern
Interface.
namespace MediatorDesignPattern
{
    internal interface IMediatorTeam
    {
        void SendMessage(string to, string from, string message);
    }
}
Implementation.

using System;

namespace MediatorDesignPattern
{
    public class MediatorTeam : IMediatorTeam
    {
        public void SendMessage(string to, string from, string message)
        {
            Console.WriteLine($"The '{message}' is sent from {from} to {to} via mediator.");
        }
    }
}
Update Team class. Both Sales and Marketing classes have MediatorTeam as property so that each class can use the method of MediatorTeam.

namespace MediatorDesignPattern
{
    public abstract class Team
    {
        public abstract string Name { get; set; }
        public abstract MediatorTeam Mediator { get; set; }
        public abstract void Send(string to, string from, string message);
    }
    public class Sales : Team
    {
        public override string Name { get; set; }
        public override MediatorTeam Mediator { get; set; }
        public override void Send(string to, string from, string message)
        {
            Mediator.SendMessage("Marketing", "Sales", "SALE 2023");
        }
    }
    public class Marketing : Team
    {
        public override string Name { get; set; }
        public MediatorTeam Mediator { get; set; }
        public override void Send(string to, string from, string message)
        {
            Mediator.SendMessage("Sales", "Marketing", "BOOM in market");
        }
    }
}
In Program.cs
namespace MediatorDesignPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Sales t1 = new Sales();
            Marketing t2 = new Marketing();
            MediatorTeam mediatorTeam = new MediatorTeam();
            t1.Name = "Sales";
            t2.Name = "Marketing";
            t1.Send(t1.Name, t2.Name,"MessageX");
            t2.Send(t2.Name, t1.Name,"MessageY");
        }
    }
}
Run the app.
We get exception.
System.NullReferenceException: 'Object reference not set to an instance of an object.'
MediatorDesignPattern.Sales.Mediator.get returned null.

To remove this error, we initialize the MediatorTeam. Since MediatorTeam is a property of Sales and Marketing, we initialize this property in MediatorTeam.
IMediator Interface

namespace MediatorDesignPattern
{
    internal interface IMediatorTeam
    {
        void Register(Team member);
        void SendMessage(string to, string from, string message);
    }
}

Mediator class. Note that in the Register method team member is initialized.

using System;
using System.Collections.Generic;
using System.Linq;

namespace MediatorDesignPattern
{
    public class MediatorTeam : IMediatorTeam
    {
        private List _teams = new List();
        public void Register(Team member)
        {
            _teams.Add(member);
            member.Mediator=this;  // initialize
        }
        public void SendMessage(string to, string from, string message)
        {
            Team team = _teams.Where(t => t.Name == to)
            .First();
            if (team != null)
            {
                Console.WriteLine($"The message '{message}' is sent from {from} to {to} via mediator.");
            }
        }
    }
}
Team class is same as before.

namespace MediatorDesignPattern
{
    public abstract class Team
    {
        public abstract string Name { get; set; }
        public abstract MediatorTeam Mediator { get; set; }
        public abstract void Send(string to, string from, string message);
    }
    public class Sales : Team
    {
        public override string Name { get; set; }
        public override MediatorTeam Mediator { get; set; }
        public override void Send(string to, string from, string message)
        {
            Mediator.SendMessage("Marketing", "Sales", "SALE 2023");
        }
    }
    public class Marketing : Team
    {
        public override string Name { get; set; }
        public override MediatorTeam Mediator { get; set; }
        public override void Send(string to, string from, string message)
        {
            Mediator.SendMessage("Sales", "Marketing", "BOOM in market");
        }
    }
}
In Program.cs We use Register method.

namespace MediatorDesignPattern
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Sales t1 = new Sales();
            Marketing t2 = new Marketing();
            MediatorTeam mediatorTeam = new MediatorTeam();
            t1.Name = "Sales";
            t2.Name = "Marketing";
            mediatorTeam.Register(t1);
            mediatorTeam.Register(t2);
            t1.Send(t1.Name, t2.Name,"MessageX");
            t2.Send(t2.Name, t1.Name,"MessageY");
        }
    }
}

Note: Creating mediator class is not enough. We must have a method in mediator class which registers the types which will use the mediator class. For this we use Register method in the above example. We could also have used Deregister method to remove a type from the mediator class.

Sunday, June 20, 2021

C# Design Pattern - Dependency Injection Pattern


Dependency
is all about dependence of one class upon another class. More the dependent one class is on other class, more they are said to be tightly coupled. In such situation, a change in independent class leads to change in the dependent class. The software architecture aims to develop loosely coupled system to allow easy maintenance and extensibility of the system.

Why Loosely Coupled System
Software development is a costly affair. The tightly coupled system or higher dependency of classes in a system makes it difficult to modify the software when business logic changes. The change of business logic is a very common phenomenon. Therefore, the software components should be loosely coupled.

The client class uses the service of service class but it might be possible that some of the services of service class can be delegated to another class. The class which is delegated those tasks is called Injector class. The injector class creates the objects of service class which are consumed by the client class and injects them into the client class. Such injected objects are called dependency objects. Dependency objects provide services. Dependency object is injected into dependent class. The injector class injects the dependency object into a class in three different ways. They are as follows.

Three Types of DI
  1. Through the constructor of client class i.e. Constructor Injector
  2. Through the public property of client class i.e. Property Injector
  3. Through the public method of client class i.e. Method Injector
First we see the example of tightly coupled system.
Data Access Layer (DAL) allows to access data from the database. It has different methods to access the data. In-memory data is used to do the same in below example.

using System;
using System.Collections.Generic;

namespace DI
{
    class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Marks { get; set; }
    }
    //
    class StudentDAL
    {
        public List<Student> students = new List<Student>()
        {
            new Student(){Id=1,Name="Amit",Marks=80},
            new Student(){Id=2,Name="Rina",Marks=60},
            new Student(){Id=3,Name="Gaurav",Marks=75},
            new Student(){Id=4,Name="Mina",Marks=55}
        };
        public List<Student>  GetStudentsDAL()
        {
            return students;
        }
    }
    //service class
    class StudentBAL
    {
        public StudentDAL allStudents;
        public List<Student> GetStudentsListBAL()
        {
            allStudents = new StudentDAL();
            return allStudents.GetStudentsDAL();
        }
    }
    //client class
    class Program
    {
        static void Main(string[] args)
        {
            StudentBAL bal = new StudentBAL();
            var list = bal.GetStudentsListBAL();
            foreach (var student in list)
            {
                Console.WriteLine("Id: {0}, Name: {1}, Marks: {2}",student.Id,student.Name, student.Marks );
            }
            Console.ReadKey();
        }
    }
}

NOTE The StudentBAL class GetStudentsListBAL method is dependent on GetStudentsDAL. So, both classes StudentBAL and StudentDAL are tightly coupled.

Constructor Injector
Now, we see the example of Constructor Injector in the following example.
using System;
using System.Collections.Generic;

namespace DI
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Marks { get; set; }
    }

    public interface IStudentDAL
    {
        List<Student> GetStudentsDAL();
    }
    public class StudentDAL : IStudentDAL
    {
        public List<Student> students = new List<Student>()
        {
            new Student(){Id=1,Name="Amit",Marks=80},
            new Student(){Id=2,Name="Rina",Marks=60},
            new Student(){Id=3,Name="Gaurav",Marks=75},
            new Student(){Id=4,Name="Mina",Marks=55}
        };
        public List<Student>  GetStudentsDAL()
        {
            return students;
        }
    }
    //service class
    class StudentBAL
    {
        private IStudentDAL _allStudents;//Dependency Object injected here
        //create constructor
        public StudentBAL(IStudentDAL allStudents)
        {
            _allStudents = allStudents;
        }
        public List<Student> GetStudentsListBAL()
        {
            return _allStudents.GetStudentsDAL();
        }
    }
    //client class
    class Program
    {
        static void Main(string[] args)
        {
            StudentBAL studentBAL = new StudentBAL(new StudentDAL());
            List<Student> list = studentBAL.GetStudentsListBAL();
            foreach (var student in list)
            {
                Console.WriteLine("Id: {0}, Name: {1}, Marks: {2}",student.Id,student.Name, student.Marks );
            }
            Console.ReadKey();
        }
    }
}
Property Injector 
We take the above example again. We inject property of Independent entity i.e. IStudentDAL into StudentBAL upon which StudentBAL is dependent.

using System;
using System.Collections.Generic;

namespace DI
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Marks { get; set; }
    }

    public interface IStudentDAL
    {
        List<Student> GetStudentsDAL();
    }
    public class StudentDAL : IStudentDAL
    {
        public List<Student> students = new List<Student>()
        {
            new Student(){Id=1,Name="Amit",Marks=80},
            new Student(){Id=2,Name="Rina",Marks=60},
            new Student(){Id=3,Name="Gaurav",Marks=75},
            new Student(){Id=4,Name="Mina",Marks=55}
        };
        public List<Student>  GetStudentsDAL()
        {
            return students;
        }
    }
    //service class
    class StudentBAL
    {
        private IStudentDAL _allStudents; //Dependency Object injected here
        //get and set to initialize the property allStudents
        public IStudentDAL allStudents
        {
            get
            {
                if (allStudents != null)
                {
                    return _allStudents;
                }
                else
                {
                    throw new Exception("Student is not initialized.");
                }
            }
            set
            {
                this._allStudents = value;
            }

        }
        //removed the constructor from previous example
        public List<Student> GetStudentsListBAL()
        {
            return _allStudents.GetStudentsDAL();
        }
    }
    //client class
    class Program
    {
        static void Main(string[] args)
        {
            StudentBAL studentBAL = new StudentBAL();
            //BAL accesses DAL through property
            studentBAL.allStudents = new StudentDAL();
            List<Student> list = studentBAL.GetStudentsListBAL();
            foreach (var student in list)
            {
                Console.WriteLine("Id: {0}, Name: {1}, Marks: {2}",student.Id,student.Name, student.Marks );
            }
            Console.ReadKey();
        }
    }
}

Method Injector
Method Injector is similar to Constructor Injector. Constructor Injector code is edited to get the following code. The constructor is deleted. The constructor dependency object is now passed to GetStudentsListBAL method. In the client class, a new Dependency object is created as method argument during GetStudentsListBAL call. 
using System;
using System.Collections.Generic;

namespace DI
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Marks { get; set; }
    }

    public interface IStudentDAL
    {
        List<Student> GetStudentsDAL();
    }
    public class StudentDAL : IStudentDAL
    {
        public List<Student> students = new List<Student>()
        {
            new Student(){Id=1,Name="Amit",Marks=80},
            new Student(){Id=2,Name="Rina",Marks=60},
            new Student(){Id=3,Name="Gaurav",Marks=75},
            new Student(){Id=4,Name="Mina",Marks=55}
        };
        public List<Student> GetStudentsDAL()
        {
            return students;
        }
    }
    //service class
    class StudentBAL
    {
        //Dependency object reference passed to method as parameter
        public List<Student> GetStudentsListBAL(IStudentDAL allStudents)
        {
            return allStudents.GetStudentsDAL();
        }
    }
    //client class
    class Program
    {
        static void Main(string[] args)
        {
            StudentBAL studentBAL = new StudentBAL();
            //Dependency object passed to method as parameter
            List<Student> list = studentBAL.GetStudentsListBAL(new StudentDAL());
            foreach (var student in list)
            {
                Console.WriteLine("Id: {0}, Name: {1}, Marks: {2}", student.Id, student.Name, student.Marks);
            }
            Console.ReadKey();
        }
    }
}



C# Design Pattern - Builder Design Pattern



Builder Design Pattern has following features
  1. It is a creational design pattern.
  2. It separates the construction of a complex object from its representation so that the same construction process can create different representations, depending upon the order of process steps and/or addition or deletion of a few process steps.
  3. Further, the steps of constructions should be independent of each other so that order of process steps can be changed. That is, the steps should not be tightly coupled.
  4. One possible solution is to create different processing steps or components of the products/classes and pass them as parameter to the constructor of the final product class. We can use Boolean parameters to decide which component will be used in the final product and null parameter to omit a component. But such constructor call becomes unwieldy. To overcome this, we use Builder Design Pattern.
  5. The products have common steps/processes/methods which are given inside abstract class or interface called Builder. These methods should be abstract and they should be overridden in the Concrete Builder classes that inherits/implements the Builder class. There are many Concrete Builder classes in BDP.
  6. The Director class is used in the BDP which defines the order in which to execute the building steps, while the Builder provides the implementation for those steps. 
  7. Having a director class in your program isn’t strictly necessary. We can always call the building steps in a specific order directly from the client code. However, the director class puts various construction routines so we can reuse them across the program.
  8. In addition, the director class completely hides the details of product construction from the client code. The client only needs to associate a builder with a director, launch the construction with the director, and get the result from the builder.
https://refactoring.guru/design-patterns/builder

C# Design Pattern - Simple Factory Design Pattern



Features of Simple Factory Design Pattern
  1. Simple Factory Design Pattern is a creational design pattern.
  2. Factory is a concrete class in simple factory design pattern which is delegated the task to create different types of objects. What type of object will be created by the factory class is decided by static get method parameter of the factory class. The important point to note is that this method returns an interface type which is inherited by all the classes which objects can be created by the factory class. These different types of objects are child classes of a parent Interface. 
  3. The logic of the object creation is hidden inside the Factory class and it is not exposed to the client class which consumes the objects created by factory class.
  4. The client class demands the object and passes the object type using parameter. The factory class creates the demanded object as per parameter.
  5. Without factory, the client class creates the object but when factory design pattern is followed, the object creation task is delegated by class to the factory class.
  6. Without factory, the client class is tightly coupled with the classes of the objects which the client class creates.
  7. The factory class has a static parameterized method which parameter is used to decide which type of object will be created by factory. 
Example
In the following example, the GetDatabase() method of DatabaseFactory class creates different types of objects but the point to note is that GetDatabase method returns IDatabase interface. This is possible because each created object's class implements IDatabase interface.

using System;
namespace SFDP
{
    interface IDatabase
    {
        void Connect();
    }
    class MySql : IDatabase
    {
        public void Connect()
        {
            Console.WriteLine("Connected with MySql database.");
        }
    }
    class Sql : IDatabase
    {
        public void Connect()
        {
            Console.WriteLine("Connected with Sql database.");
        }
    }
    class Oracle : IDatabase
    {
        public void Connect()
        {
            Console.WriteLine("Connected with Oracle database.");
        }
    }
//factory class
    class DatabaseFactory
    {
        public static IDatabase GetDatabase(string databaseName)
        {
            switch (databaseName.ToLower())
            {
                case "sql":
                    return new Sql();
                case "oracle":
                    return new Oracle();
                case "mysql":
                    return new MySql();
                default:
                    return null;
            }
        }
    }
//client class
    class Program
    {
        static void Main(string[] args)
        {
            IDatabase db = DatabaseFactory.GetDatabase("Oracle");
            if (db != null)
            {
                db.Connect();
            }
            else
            {
                Console.WriteLine("Connection failed...");
            }
        }
    }
}

C# Design Pattern - Abstract Factory Design Pattern





Look at the following hierarchy of teachers.

Abstraction of top level -> Teacher 
Abstraction of middle level -> ScienceTeacher and ArtTeacher
Concrete classes at the bottom level -> PhysicsTeacher, ChemistryTeacher, BiologyTeacher, HindiTeacher, EnglishTeacher

Step1. Top level abstract Class/Interface
All teachers teach. This method will be included in the Teacher, top level abstraction. Abstraction can be as interface or abstract class.

public interface Teacher
    {
        string teach();
    }
Step2. Bottom level all Concrete Classes
public class PhysicsTeacher : Teacher
{
    public string teach()
        {
            return "Physics";
        }
}
public class ChemistryTeacher : Teacher
{
    public string teach()
        {
            return "Chemistry";
        }
}
public class BiologyTeacher : Teacher
{
    public string teach()
        {
            return "Biology";
        }
}
public class HindiTeacher : Teacher
{
    public string teach()
        {
            return "Hindi";
        }
}
public class EnglishTeacher : Teacher
{
    public string teach()
        {
            return "English";
        }
}
Step3. Create top level abstract TeacherFactory
    public abstract class TeacherFactory
    {
        public abstract Teacher getTeacher(string TeacherType);
        public static TeacherFactory CreateTeacherFactory(string FactoryType)
        {
            if (FactoryType.Equals("science"))
                return new ScienceTeacherFactory();
            else if (FactoryType.Equals("art"))
                return new ArtTeacherFactory();
            else return null;
        }
    }
Thus, at the top level abstraction, factory will be TeacherFactory. This will return Teacher as per their type (parameter will decide) and similarly it will have static method CreateTeacherFactory which will return either ScienceTeacherFactory or ArtTeacherFactory.

Step4. Create mid level all concrete factory classes which will inherit top level abstract TeacherFactory

    public class ScienceTeacherFactory : TeacherFactory
    {
        public override Teacher getTeacher(string TeacherType)
        {
            switch (TeacherType)
            {
                case "physics": return new PhysicsTeacher();
                case "chemistry": return new ChemistryTeacher();
                case "biology": return new BiologyTeacher();
                default: return null;
            }
        }

    }
    public class ArtTeacherFactory : TeacherFactory
    {
        public override Teacher getTeacher(string TeacherType)
        {
            switch (TeacherType)
            {
                case "hindi": return new HindiTeacher();
                case "english": return new EnglishTeacher();
                default: return null;
            }
        }
    }
   
Step5. Client class will consume the classes.
 class Program
    {
        static void Main(string[] args)
        {
            Teacher teacher = null;
            TeacherFactory teacherFactory = null;
            teacherFactory = TeacherFactory.CreateTeacherFactory("science");
            Console.WriteLine("Teacher Factory type : " + teacherFactory.GetType().Name);
            teacher = teacherFactory.getTeacher("physics");
            Console.WriteLine("Teacher Type: " + teacher.GetType().Name);
            Console.WriteLine("Teaches: " + teacher.teach());

            teacherFactory = TeacherFactory.CreateTeacherFactory("art");
            Console.WriteLine("Teacher Factory type : " + teacherFactory.GetType().Name);
            teacher = teacherFactory.getTeacher("hindi");
            Console.WriteLine("Teacher Type: " + teacher.GetType().Name);
            Console.WriteLine("Teaches: " + teacher.teach());
            Console.ReadLine();

        }
    }
}
Complete Code
using System;
namespace AFC
{
    public interface Teacher
    {
        string teach();
    }
    public class PhysicsTeacher : Teacher
    {
        public string teach()
        {
            return "Physics";
        }
    }
    public class ChemistryTeacher : Teacher
    {
        public string teach()
        {
            return "Chemistry";
        }
    }
    public class BiologyTeacher : Teacher
    {
        public string teach()
        {
            return "Biology";
        }
    }
    public class HindiTeacher : Teacher
    {
        public string teach()
        {
            return "Hindi";
        }
    }
    public class EnglishTeacher : Teacher
    {
        public string teach()
        {
            return "English";
        }
    }

    public abstract class TeacherFactory
    {
        public abstract Teacher getTeacher(string TeacherType);
        public static TeacherFactory CreateTeacherFactory(string FactoryType)
        {
            if (FactoryType.Equals("science"))
                return new ScienceTeacherFactory();
            else if (FactoryType.Equals("art"))
                return new ArtTeacherFactory();
            else return null;
        }
    }
    public class ScienceTeacherFactory : TeacherFactory
    {
        public override Teacher getTeacher(string TeacherType)
        {
            switch (TeacherType)
            {
                case "physics": return new PhysicsTeacher();
                case "chemistry": return new ChemistryTeacher();
                case "biology": return new BiologyTeacher();
                default: return null;
            }
        }

    }
    public class ArtTeacherFactory : TeacherFactory
    {
        public override Teacher getTeacher(string TeacherType)
        {
            switch (TeacherType)
            {
                case "hindi": return new HindiTeacher();
                case "english": return new EnglishTeacher();
                default: return null;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Teacher teacher = null;
            TeacherFactory teacherFactory = null;
            teacherFactory = TeacherFactory.CreateTeacherFactory("science");
            Console.WriteLine("Teacher Factory type : " + teacherFactory.GetType().Name);
            teacher = teacherFactory.getTeacher("physics");
            Console.WriteLine("Teacher Type: " + teacher.GetType().Name);
            Console.WriteLine("Teaches: " + teacher.teach());

            teacherFactory = TeacherFactory.CreateTeacherFactory("art");
            Console.WriteLine("Teacher Factory type : " + teacherFactory.GetType().Name);
            teacher = teacherFactory.getTeacher("hindi");
            Console.WriteLine("Teacher Type: " + teacher.GetType().Name);
            Console.WriteLine("Teaches: " + teacher.teach());
            Console.ReadLine();

        }
    }
}


 

C# Design Pattern - Factory Method Design Pattern



Features of Factory Method Design Pattern
  1. Factory Method Design Pattern is a creational design pattern.
  2. In this design pattern, there is an interface which is derived by classes of different types of objects. The interface contains methods to get generic details of each type of objects to be created. For example, Garment is the super Interface which contains methods to get type of garment and units of garment. Now to create each type of derived classes, abstract factory class or interface is used.
  3. Interface factory or abstract factory class  is used which is derived by concrete factories. The interface factory does not create objects. It is the responsibility of concrete factory classes.
Example: We have generic garment IGarment and generic factory IGarmentFactory. The generic IGarment contains the methods to get type of Garment and units of Garment. The IGarmentFactory contains abstract method which is implemented by each subtype class of IGarment. 

using System;
namespace FactoryMethodDesign
{
    public interface IGarment
    {
        string getGarmentType();
        int getGarmentUnits();
    }
//Concrete class
    public class Shirt : IGarment
    {
        public string getGarmentType()
        {
            return "Shirt";
        }

        public int getGarmentUnits()
        {
            return 2;
        }
    }
//Concrete class
    public class Pant : IGarment
    {
        public string getGarmentType()
        {
            return "Pant";
        }

        public int getGarmentUnits()
        {
            return 3;
        }
    }

    // Factory class is an interface or abstract class in Factory Mathod Design
    // protected abstract method GetGarment will be implemented by derived class
    public abstract class IGarmentFactory
    {
        protected abstract IGarment GetGarment();
        public IGarment CreateGarment()
        {
            return this.GetGarment();
        }
    }
//Concrete Factory/Creator class
    public class ShirtFactory : IGarmentFactory
    {
        protected override IGarment GetGarment()
        {
            IGarment garment = new Shirt();
            return garment;
        }
    }
//Concrete Factory/Creator class
    public class PantFactory : IGarmentFactory
    {
        protected override IGarment GetGarment()
        {
            IGarment garment = new Pant();
            return garment;
        }
    }

//Client class
    class Program
    {
        static void Main(string[] args)
        {
            IGarment garment = new ShirtFactory().CreateGarment();
            Console.Write(garment.getGarmentType());
            Console.Write(garment.getGarmentUnits());
            Console.WriteLine();
            IGarment garment2 = new PantFactory().CreateGarment();
            Console.Write(garment2.getGarmentType());
            Console.Write(garment2.getGarmentUnits());
            Console.ReadKey();
        }
    }
}



Hot Topics