Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

c#
design pattern
communitycreator

Implementing the abstract factory design pattern in C#

Similoluwa Adegoke

The Abstract Factory Design Pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.

Use case:

Say we are building a school management application for several schools, and a feature we need to build involves listing courses offered to students based on school and department.

Let’s begin solving it

Our aim is to list courses offered by a student object based on the department (one factory) and the school (another factory).

First, we create an interface for the student object. Create a Student.cs file and write the code below in it.

namespace  AbstractFactoryDesign 
{
    public interface IStudent
    {
        List<string> Courses();
    }   
}
The interface specifies a method (Courses) that returns a string list of courses.

Next, ​we create the student object of various schools and departments. The two schools we are using are FUTA and UI. I suffixed the class name with the school name to create the distinction


namespace AbstractFactoryDesign
{
    public class BioStudentFuta : IStudent
    {
        public List<string> Courses()
        {
            return new List<string>{"Bio 101", "Bio 201"};
        }
    }
    public class ChemStudentFuta : IStudent
    {
        public List<string> Courses()
        {
            return new List<string>{"Chem 101", "Chem 201"};
        }
    }

    public class GeoStudentFuta : IStudent
    {
        public List<string> Courses()
        {
            return new List<string>{"Geo 101", "Chem 201"};
        }
    }
    public class MedStudentUI : IStudent
    {
        public List<string> Courses()
        {
            return new List<string>{"SRG 101", "SRG 102"};
        }
    }

    public class MechStudentUI : IStudent
    {
        public List<string> Courses()
        {
            return new List<string>{"MEE 101", "MEE 102"};
        }
    }
}

Now, we want to build the school factory.

Think like this, a factory is where products are made. Building a school factory will produce schools.

So, we need to build a factory that produces two schools: UI and FUTA

namespace AbstractFactoryDesign
{
    public abstract class StudentFactory
    {
        public abstract IStudent GetStudent(string studentDept);

        public static StudentFactory CreateStudentFactory(string studentSch)
        {
            if(studentSch.Equals("UI"))
                return new UIStudentFactory();
            else
                return new FutaStudentFactory();
        }
    }
}
This class produces either the UIStudentFactory or the FutaStudentFactory

There are two methods here:

  1. An abstract method that returns a student object (IStudent) based on the studentDept.
  2. A static method that returns an object of type UIStudent or FUTAStudent based on the string studentSch.

Now that we have written the factory that produces school, we need to write the department factory that produces the students by department.

Here:

 public class UIStudentFactory : StudentFactory
    {
        public override IStudent GetStudent(string studentDept)
        {
            if(studentDept.Equals("Med"))
                return new MedStudentUI();
            else if(studentDept.Equals("Mech"))
                return new MechStudentUI();
            else
                return null;
        }
    }

    public class FutaStudentFactory : StudentFactory
    {
        public override IStudent GetStudent(string studentDept)
        {
            if(studentDept.Equals("Geo"))
                return new GeoStudentFuta();
            else if(studentDept.Equals("Bio"))
                return new BioStudentFuta();
            else if(studentDept.Equals("Chem"))
                return new ChemStudentFuta();
            else 
                return null;
        }
    }

The UIStudentFactory class and the FUTAStudentFactory class both inherit from the abstract StudentFactory Class.

The two classes are both factories that produce the student object based on the studentDept.

It is important to point out that the Abstract Class they both inherited from does not know about them; hence, the term abstract.

Finally, we can consume it on the client.

 class Program
    {
        static void Main(string[] args)
        {
            IStudent student = null;
            StudentFactory studentFactory = null;
            List<string> courses = null;
            
            //create a UI student factory by passing the factory type as UI
            studentFactory = StudentFactory.CreateStudentFactory("UI");
            Console.WriteLine("Student School: "+ studentFactory.GetType().Name);

            // get bio student by passing the student type. 
            student = studentFactory.GetStudent("Med");
            Console.WriteLine("Student Dept: "+ student.GetType().Name);
            courses = student.Courses();
            foreach (var item in courses)
            {
                Console.WriteLine("Course code: "+ item);
            }
            Console.WriteLine();

            Console.WriteLine("------------------------------");

            Console.ReadLine();
        }
    }

In the above code we:

  1. Declared the objects needed: student, studentFactory, and courses
  2. Then, we called the factory that produces schools (StudentFactory) to create a school (CreateStudentFactory) by passing the school name (UI).
  3. Then, we called the produced factory (studentFactory) to produce for us the student object based on the department (Med).

And just like that, we have solved a problem without writing a lot of if statements. In the event that we wanted to add another school, it would be easier to do so.

Always remember to think of Abstract Factory Design Pattern as about building an abstract factory (not concerned with reality) of factories.

RELATED TAGS

c#
design pattern
communitycreator
RELATED COURSES

View all Courses

Keep Exploring