Advertisement
Поиск  
Always will be ready notify the world about expectations as easy as possible: job change page
Jan 31

Factory Pattern — C#

Factory Pattern — C#
Автор:
Источник:
Просмотров:
534

This is a creational pattern that provides a way to create an object without exposing the creation logic for the users of it. There are two well-known approaches that I will explain and show how and when you should use them.

Abstract Factory

This type of factory creates families of objects that are related to each other without specifying their concrete classes.

Example

Let’s say that we have a burger industry and we are able to create beef burgers and vegetarian burgers. The main idea is to have multiple clients that use my factory to create their burgers to sell them in their restaurants or markets.

The abstraction of BurgerFactory with two implementations
The abstraction of BurgerFactory with two implementations

To create a beef burger they need to specify the fat percentage that will exist in the composition of the burger. For the vegetarian ones, they need to define the base vegetable that will be used to create them. These two requirements are part of our factory interface IBurgerFactory.

The abstraction of Beef and Vegetarian Burger
The abstraction of Beef and Vegetarian Burger

We have our first client! A low cost burger company contact us to produce their burgers. The first thing is to define the specific classes that implement the previous interfaces.

public class LowCostVegetarianBurger : IVegetarianBurger
{
    public string GetBaseVegetable() => "Chickpea";
}

public class LowCostBeefBurger : IBeefBurger
{
    public int GetFatPercentage() => 5;
}

Now we need to create the concrete factory that implements the required interface.

public class LowCostBurgerFactory : IBurgerFactory
{
    public LowCostBurgerFactory()
    {
    }

    public IBeefBurger CreateBeefBurger()
    {
        return new LowCostBeefBurger();
    }

    public IVegetarianBurger CreateVegetarianBurger()
    {
        return new LowCostVegetarianBurger();
    }
}

What if I don’t want some type of burger?

Just return null or an exception if you prefer. However, if this is a recurrent situation I advise you to create two different interfaces. One just for beef burger factories and another for vegetarian burgers factories. You will have IBeefBurgerFactory and IVegetarianBurgerFactory instead of IBurgerFactory.

How can use it?

IBurgerFactory lowCostFactory = new LowCostBurgerFactory();
_logger.LogInformation($"Beef Burger fat percentage: {lowCostFactory.CreateBeefBurger().GetFatPercentage()}");
_logger.LogInformation($"Vegetarian Burger base: {lowCostFactory.CreateVegetarianBurger().GetBaseVegetable()}");

This is a simple example to understand the purpose of this factory approach. You will certainly add more complexity to the creation of your objects.

Factory Method

This type of factory gives an interface to create objects in a superclass. However, allows that the subclasses decide the type of objects that will be created.

Example

We received a request from a mobile application that manages orders to restaurants. This app needs to show the restaurant menu to its users.
Let’s create a factory to be inherited by any restaurant in order to create their menus.
The most important thing to do is to define an abstract class that has a GetMenu() method. This will be our factory method.

The abstract class MenuFactory with two implementations
The abstract class MenuFactory with two implementations

Every restaurant factory must extend this class and implement the abstract method. Having a main abstract factory allows us to provide other methods to be used by any child class, the method GetPrice() has that purpose.

public abstract class MenuFactory
{
    public abstract Menu GetMenu();
    
    public float GetPrice(string itemName)
    {
        Menu menu = GetMenu();
        MenuItem menuItem = menu.Items.SingleOrDefault(m => m.Name == itemName);
        if (menuItem != null)
            return menuItem.Price;

        return 0;
    }
}

The following code block shows an example of a restaurant factory.

public class BurgerRestaurantFactory : MenuFactory
{
    private readonly string _restaurantName;

    public BurgerRestaurantFactory()
    {
        _restaurantName = "Burger Shot";
    }

    public override Menu GetMenu()
    {
        List<MenuItem> menuItems = new List<MenuItem>()
        {
            new MenuItem("Smash Burger", 3),
            new MenuItem("Cheese Burger", 4),
            new MenuItem("Bacon Cheese Burger", 5.49f),
            new MenuItem("Smash Burger Combo", 5.99f)
        };

        return new Menu(_restaurantName, menuItems);
    }
}

This is a simple example, this burger restaurant doesn’t add anything besides the menu and its name. However, we know that this class can be, and probably will, more complex than this.

How can use it?

MenuFactory burgerRestaurantFactory = new BurgerRestaurantFactory();
Menu burgerMenu = burgerRestaurantFactory.GetMenu();string itemName = "Bacon Cheese Burger";
float baconCheesePrice = burgerRestaurantFactory.GetPrice(itemName);
_logger.LogInformation($"The restaurant {burgerMenu.RestaurantName} has a {itemName} for {baconCheesePrice}.");

You can get the menu from that restaurant and use the method to get the price of some specific item.

Conclusion

This pattern is really good to have in your hand when you want to develop any type of system. Its focus is on the creation of more complex objects where you have to create multiple other objects that compose it. The two approaches that were presented are equally good options, you just need to understand the differences and choose the one that better fits your necessities.
Besides all that was said and explained I just need to add one thing: Yes I love burgers.

Похожее
Feb 10, 2023
Author: Hr. N Nikitins
Design patterns are essential for creating maintainable and reusable code in .NET. Whether you’re a seasoned developer or just starting out, understanding and applying these patterns can greatly improve your coding efficiency and overall development process. In this post, we’ll...
Jan 1, 2023
Author: Daniel Kreider
Here’s the simple step-by-step guide that will teach you how to build and code a generic repository.There are oodles of design patterns.Some of these design patterns are floating about on antique blogs full of mad logic. They’re ridiculous enough to...
Oct 26, 2023
Author: Genny Allcroft
Key strategic and tactical considerations to take when building a new product with the domain-driven design concepts in mindI have just finished reading Learning Domain-Driven Design by Vlad Khononov. It’s quite a short book (c. 300 pages) aiming to teach...
Oct 24, 2022
Author: Henrique Siebert Domareski
Singleton and Static classes can only have one instance available in memory, and both classes can be used to maintain the global state of an application, however, there are many differences between them. In this article, I explain what their...
Написать сообщение
Почта
Имя
*Сообщение


© 1999–2024 WebDynamics
1980–... Sergey Drozdov
Area of interests: .NET Framework | .NET Core | C# | ASP.NET | Windows Forms | WPF | HTML5 | CSS3 | jQuery | AJAX | Angular | React | MS SQL Server | Transact-SQL | ADO.NET | Entity Framework | IIS | OOP | OOA | OOD | WCF | WPF | MSMQ | MVC | MVP | MVVM | Design Patterns | Enterprise Architecture | Scrum | Kanban