C# Abstract Factory Design Pattern With Code Example

C# Abstract Factory Design Pattern With Code Example

Preface

I came across the Abstract Factory Design Pattern a few weeks ago, after days of study I think I managed to grasp the concept of this design pattern. So I decided to share some learning experiences about it. First,  I will show example code of “before and after” applying the design pattern. I will use Interface and abstract class separately to achieve the goal, and finally, I will write some ‘Nested Abstract Factory’ code for some fun experiment. Please feel free to leave your comment to correct me, or let me know if you possess any new idea about my code. Thanks.

Without Abstract Factory

I’m using furniture as an example. The furniture is categorized by design, which are Classic, Contemporary, and Scandinavian. The furniture itself has 3 different objects, which are Cabinet, Chair and Dining Table, so there will be 9 different combinations, as the table below shows.

C# Abstract Factory Design Pattern With Code Example

When the console program of furniture creation run, it will look something like this,

C# Abstract Factory Design Pattern With Code Example

For code design, each piece of furniture will have its own class, for example, a cabinet belongs to classic design, I will name it ClassicCabinet. Each cabinet has two methods. FurnitureFunction() is to show the function of the furniture, function of all cabinets, regardless of design. ShowStyle() method is meant to show the design style of each furniture respectively, for this case classic cabinet will display a message “I’m a Classical cabinet”

public class ClassicCabinet {
    public void FurnitureFunction() {
        Console.WriteLine("I'm used for storing item");
    }
    public void ShowStyle() {
        Console.WriteLine("I'm a Classical cabinet ");
    }
}

This is the main program, I use Switch-Case to do the condition checking, and initial corresponding furniture class. As you can see, for Classic design, I have to use another Switch-Case for 3 different furniture.

do {
    Console.WriteLine("Please select your desired design style:");
    Console.WriteLine("[1]Classic, [2]Contemporary, [3]Scandinavian");
    int.TryParse(Console.ReadLine(), out design);
}
while (design == 0 || design > 3);
switch (design) {
    case 1: //Classic
        do {
            Console.WriteLine("Seems like you prefer Classic design!");
            Console.WriteLine("Please select your desired furniture :");
            Console.WriteLine("[1]Cabinet, [2]Chair, [3]Dining Table");
            int.TryParse(Console.ReadLine(), out furniture);
        } while (furniture == 0 || furniture > 3);
        switch (furniture) {
            case 1: //Cabinet
                Console.WriteLine("Terrific choice! We sell the best cabinet in the town!");
                ClassicCabinet cabinet = new ClassicCabinet();
                cabinet.ShowStyle();
                cabinet.FurnitureFunction();
                break;

The same things repeat for Contemporary and Scandinavian:

case 2: //Contemporary
    do {
        Console.WriteLine("Seems like you prefer Contemporary design!");
        Console.WriteLine("Please select your desired furniture :");
        Console.WriteLine("[1]Cabinet, [2]Chair, [3]Dining Table");
        int.TryParse(Console.ReadLine(), out furniture);
    } while (furniture == 0 || furniture > 3);
switch (furniture) {
    case 1: //Cabinet
        Console.WriteLine("Terrific choice! We sell the best cabinet in the town!");
        ContemporaryCabinet cabinet = new ContemporaryCabinet();
        cabinet.ShowStyle();
        cabinet.FurnitureFunction();
        break;
    case 2: //Chair
        Console.WriteLine("Terrific choice! We sell the best chair in the town!");
        ContemporaryChair chair = new ContemporaryChair();
        chair.ShowStyle();
        chair.FurnitureFunction();
        break;
    case 3: //Dinning table
        Console.WriteLine("Terrific choice! We sell the best dining table in the town!");
        ContemporaryDiningTable diningtable = new ContemporaryDiningTable();
        diningtable.ShowStyle();
        diningtable.FurnitureFunction();
        break;

For this simple example, I already created 9 conditions,  and there is only 3 furniture. Imagine if in real life a furniture shop can have like 100 different furniture and more than 3 design styles, the amount of condition will become tremendous and very difficult to maintain.

Then, the Abstract Factory came into help.

By textbook definition, Abstract Factory is a creational design pattern that lets you produce families of related objects without specifying their concrete classes.

I doubt if anyone can understand any programming concept by solely looking at the definition, so I better continue to demonstrate this pattern by showing some example code.

Abstract Factory with Interface

First, for the furniture itself. Since all the furniture share a common method, I create an Interface named IFurniture to be implemented by all furniture classes.

public interface IFurniture {
    void FurnitureFunction();
    void ShowStyle();
}

Second, since the furniture factory needs to produce a cabinet, chair, and dining table nevertheless, I will create an Interface called IFurnitureFactory that will be implemented by a different design style factory. This factory will have 3 methods that create above mentioned furniture, the data type of IFurniture.

public interface IFurnitureFactory {
    IFurniture CreateCabinet();
    IFurniture CreateChair();
    IFurniture CreateDiningTable();
}

Enough for abstraction, let’s create some concrete. In Abstract Factory Design Pattern terminology, we will have some factory called Concrete Factory/Class that creates the real object. In this case, I have ClassicFurnitureFactory, ContemporaryFurnitureFactory, and ScandinavianFurnitureFactory. Each concrete factory creates its own category factory. For example, ClassicFurnitureFactory creates all Classic furniture.

public class ClassicFurnitureFactory: IFurnitureFactory {
    public IFurniture CreateCabinet() {
        return new ClassicCabinet();
    }
    public IFurniture CreateChair() {
        return new ClassicChair();
    }
    public IFurniture CreateDiningTable() {
        return new ClassicDiningTable();
    }
}

One more example, ScandinavianFurnitureFactory creates all Scandinavian furniture.

public class ScandinavianFurnitureFactory: IFurnitureFactory {
    public IFurniture CreateCabinet() {
        return new ScandinavianCabinet();
    }
    public IFurniture CreateChair() {
        return new ScandinavianChair();
    }
    public IFurniture CreateDiningTable() {
        return new ScandinavianDiningTable();
    }
}

Each furniture has its own class with its own customized message, for simplicity I show the code of ContemporaryCabinet class.

public class ContemporaryCabinet: IFurniture {
    public void FurnitureFunction() {
        Console.WriteLine("I'm used for storing item");
    }
    public void ShowStyle() {
        Console.WriteLine("I'm a Contemporary cabinet ");
    }
}

In a simple sentence to summarize my understanding of the Abstract Factory, it is Concrete Factory creates a Concrete Product, and Concrete Factory implements Abstract Factory, and Concrete Product implements Abstract Product.  

If you are a diagram person, the UML class diagram will look like this: (sorry for the poor drawing, but I believe my code are pretty self explain itself for you)

C# Abstract Factory Design Pattern With Code Example

C# Abstract Factory Design Pattern With Code Example

We are almost done here, now for the main program.

do {
    Console.WriteLine("Please select your furniture style:");
    Console.WriteLine("[1]Classic, [2]Contemporary, [3]Scandinavian");
    int.TryParse(Console.ReadLine(), out style);
}
while (style == 0 || style > 3);
IFurnitureFactory Factory = null;
switch (style) {
    case 1:
        Factory = new ClassicFurnitureFactory();
        break;
    case 2:
        Factory = new ContemporaryFurnitureFactory();
        break;
    case 3:
        Factory = new ScandinavianFurnitureFactory();
        break;
}
do {
    Console.WriteLine("Please select your furniture :");
    Console.WriteLine("[1]Cabinet, [2]Chair, [3]Dining Table");
    int.TryParse(Console.ReadLine(), out furniture);
}
while (furniture == 0 || furniture > 3);
IFurniture furnitureProduct = null;
switch (furniture) {
    case 1:
        furnitureProduct = Factory.CreateCabinet();
        break;
    case 2:
        furnitureProduct = Factory.CreateChair();
        break;
    case 3:
        furnitureProduct = Factory.CreateDiningTable();
        break;
}
Console.WriteLine("Furniture Created: ");
furnitureProduct.ShowStyle();
furnitureProduct.FurnitureFunction();

As you can see, I don’t need to initiate the furniture (e.g. ClassicCabinet) itself, I just need to create the corresponding factory by user’s selection and store it into the variable “Factory”. “Factory” Variables can be either Classic, Contemporary or Scandinavian design, and it creates the corresponding furniture. For example, if the factory we create is from Contemporary Factory, so the chair it creates will automatically became “ContemporaryChair” object.

Abstract Factory with Abstract Class, Inheritance

Same Abstract Factory Design Pattern can be achieved by using abstract class inheritance methods.

The overall design is still more or less similar.

First I created an abstract class called Furniture, which has two methods. One is a virtual method called FurnitureFunction(), another is an abstract ShowStyle. Since we know that both methods will be overridden, I should set both methods as abstract instead of virtual, but for the sake of demo, I just make them different.

public abstract class Furniture {
    public virtual void FurnitureFunction() {
        Console.WriteLine("Dummy furniture function");
    }
    public abstract void ShowStyle();
}

Another base class is FurnitureFactory, which has 3 abstract methods that must be overridden.

public abstract class FurnitureFactory {
    public abstract Furniture CreateCabinet();
    public abstract Furniture CreateChair();
    public abstract Furniture CreateDiningTable();
}

For the concrete factory, it is the same with the above example, we have ClassicFurnitureFactory, ContemporaryFurnitureFactory, and ScandinavianFurnitureFactory. I showed one of them, ContemporaryFactory. As you can see, this factory inherit from FurnitureFactory and override all the methods

public class ContemporaryFactory: FurnitureFactory {
    public override Furniture CreateCabinet() {
        return new ContemporaryCabinet();
    }
    public override Furniture CreateChair() {
        return new ContemporaryChair();
    }
    public override Furniture CreateDiningTable() {
        return new ContemporaryDiningTable();
    }
}

Same thing happens to the furniture class,  they inherit from the Furniture base class and override the parent method with their own.

public class ScandinavianCabinet: Furniture {
    public override void FurnitureFunction() {
        Console.WriteLine("I'm used for storing item");
    }
    public override void ShowStyle() {
        Console.WriteLine("I'm a Scandinavian cabinet ");
    }
}

Again, for diagram person, the UML class diagram will look like this:

C# Abstract Factory Design Pattern With Code Example

C# Abstract Factory Design Pattern With Code Example

The main program is the same, so I skip the code demo. You can get my full source code via Github at the end of this article.

It depends on the design,

From above 2 examples that either using interface or abstract class, my interface/base class is the design style of the furniture, and the product is furniture itself, how about if we inverse the relationship, can we create a factory that creates furniture, and the product is the design style?

I create an Interface called IStyles that will be implemented by abstract factory classes. This interface has two methods, one is to show the design philosophy of each design, and another is to display the major build material for that design.

public interface IStyles {
    void DesignPhilosophy();
    void BuildMaterials();
}

Another Interface is IStyleFactory to be implemented by the concrete classes, as you can see, our concrete product will create 3 different design respectively.

public interface IStyleFactory {
    IStyles CreateClassic();
    IStyles CreateContemporary();
    IStyles CreateScandinavian();
}

Example of one Concrete Factory class, CabinetFactory, it implements the IStyleFactory, it creates cabinet only, but will different style.

public class CabinetFactory: IStyleFactory {
    public IStyles CreateClassic() {
        return new ClassicCabinet();
    }
    public IStyles CreateContemporary() {
        return new ContemporaryCabinet();
    }
    public IStyles CreateScandinavian() {
        return new ScandinavianCabinet();
    }
}

Example of one Concrete Product class, ClassicCabinet, shows the detailed implementations of the logic of classic design of cabinet.

public class ClassicCabinet: IStyles {
    public void DesignPhilosophy() {
        Console.WriteLine("This style inspiration from English and French styles of the " + "18th and 19th centuries");
    }
    public void BuildMaterials() {
        Console.WriteLine("This style build by oak, cherry, walnut and birch. " + "As for the upholstery, it is brocade, satin, velvet, silk and leather");
    }
}

The client main code will look more or less the same as the previous example, just change the question order. The console output will look something like this.

C# Abstract Factory Design Pattern With Code Example

Nested 3 Level Abstract Factory?

I read a few articles and one pdf book about the Abstract Factory for the past few days, but I never found any example with more than 2 levels. So, I decided to add one more level, try to create something like the ‘Abstract Factory of the Abstract Factory’. Just a reminder, this ‘Nested Abstract Factory’ is just some fun experiment by myself to test my understanding of the factory, please let me know if my approach is wrong or if there is a better way to do it.  

I still take this furniture factory as an example, but I will add one more level of categorization called “Marketing”. That means for our furniture products, it either be Art category, or fall into commercial category. For the Art category, we will emphasize the myth or fiction about each design, tied to the furniture itself. For the commercial category, we will display the price of the furniture. (I know this might not be a good example, but just for the sake of the demo please bear with my dummy example)

For simplicity (pronounced: lazy to code more repeated classes), I reduce the design and furniture to 2, then we will have 8 different products, instead of 18 (3 x 3 x 2)

C# Abstract Factory Design Pattern With Code Example

The UML class looks like this:

C# Abstract Factory Design Pattern With Code Example

Again, sorry for my poor drawing. First, there are Contemporary and Scandinavian Factories, both factories will create their own Art and Commercial Factory. It is like ‘factory creates another factory’, and finally both the Art and Commercial factory will create their own furniture, will the properties be stacked. For example, if a Contemporary Factory creates an Art Factory, and an Art Factory finally creates a Chair, so the chair will have properties of their parent and grandparent, become a Contemporary Art Chair.

For a better understanding of my design, let’s have a walkthrough of my code.

public interface IFurniture {
    void FurnitureFunction();
    void FurnitureStyle();
}
public interface IArtFurniture: IFurniture {
    void FictionOrMythStory();
}
public interface ICommercialFurniture: IFurniture {
    void Price();
}

First is the Interface, IFurniture is like the previous example, 2 methods to show furniture function and design style. And since we have 2 different marketing categories, and each have different methods, so I split it into two:

IArtFurniture with its own FictionOrMythStory() method, and ICommercialFurniture with its own Price() method. Our concrete product later will implement multiple interfaces.  

public interface IFurnitureFactory {
    IFurniture CreateChair();
    IFurniture CreateDiningTable();
}
public interface IDesignFactory {
    IFurnitureFactory GetMarketingFactory(string marketingFactoryType);
}

IFurnitureFactory to standardize create chair and dining table function, IDesignFactory interface contains function to get marketing factory (Art or Commercial)

public class ContemporaryFactory: IDesignFactory {
    public IFurnitureFactory GetMarketingFactory(string marketingFactoryType) {
        switch (marketingFactoryType) {
            case nameof(ArtFactory):
                return new ArtFactory(nameof(ContemporaryFactory));
            case nameof(CommercialFactory):
                return new CommercialFactory(nameof(ContemporaryFactory));
            default:
                return null;
        }
    }
}

ContemporaryFactory class, this class will create the factory for Art or Commercial, based on the value passed in. Art of Commercial factory created by this class, will stack will properties of Contemporary as well.   (Same thing happen for ScandinavianFactory class)

public class ArtFactory: IFurnitureFactory {
    private readonly string DesignName;
    public ArtFactory(string designName) {
        DesignName = designName;
    }
    public IFurniture CreateChair() {
        switch (DesignName) {
            case nameof(ScandinavianFactory):
                return new ScandinavianArtChair();
            case nameof(ContemporaryFactory):
                return new ContemporaryArtChair();
            default:
                return null;
        }
    }
    public IFurniture CreateDiningTable() {
        switch (DesignName) {
            case nameof(ScandinavianFactory):
                return new ScandinavianArtDiningTable();
            case nameof(ContemporaryFactory):
                return new ContemporaryArtDiningTable();
            default:
                return null;
        }
    }
}

ArtFactory class, this class will create a chair or a dining table based on input. Same thing happens for CommercialFactory.

do {
    Console.WriteLine("Please select your desired design style: [1]Contemporary, [2]Scandinavian");
    int.TryParse(Console.ReadLine(), out design);
} while (design <= 0 || design > 2);
switch (design) {
    case 1:
        Console.WriteLine("Seems like you prefer Contemporary design!");
        designFactory = new ContemporaryFactory();
        break;
    case 2:
        Console.WriteLine("Seems like you prefer Scandinavian design!");
        designFactory = new ScandinavianFactory();
        break;
    default:
        designFactory = null;
        break;
}
do {
    Console.WriteLine("Now, please select your preference type : [1]Art, [2]Commercial");
    int.TryParse(Console.ReadLine(), out marketing);
} while (marketing <= 0 || marketing > 2);
switch (marketing) {
    case 1:
        Console.WriteLine("Cool! Seems like you are an artistic person!");
        furnitureFactory = designFactory.GetMarketingFactory(nameof(ArtFactory));
        break;
    case 2:
        Console.WriteLine("Cool! Seems like you are fond with commercial world!");
        furnitureFactory = designFactory.GetMarketingFactory(nameof(CommercialFactory));
        break;
    default:
        furnitureFactory = null;
        break;
}
do {
    Console.WriteLine("Finally, please select your desired furniture: [1]Chair, [2]Dining Table");
    int.TryParse(Console.ReadLine(), out furniture);
} while (furniture <= 0 || furniture > 2);
switch (furniture) {
    case 1:
        Console.WriteLine("Terrific choice! We sell the best chair in the town!");
        product = furnitureFactory.CreateChair();
        break;
    case 2:
        Console.WriteLine("Terrific choice! We sell the best dining table in the town!");
        product = furnitureFactory.CreateDiningTable();
        break;
    default:
        product = null;
        break;
}

Main program, 3 switch statements to get 3 different things before creating the furniture. Logic is pretty similar to the previous example, but just an extra one more level.

The console program will show something like this,

C# Abstract Factory Design Pattern With Code Example

Conclusion

Abstract Factory is one of the popular design patterns. I hope you enjoy my writing and can have a better understanding of this pattern. Again, please feel free to let me know if I did something wrong in this article.

Full source code of my project can be downloaded via Github.


Similar Articles