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

When to use it Abstract Factory Design Pattern

When to use it Abstract Factory Design Pattern

 The Abstract Factory Design Pattern is particularly useful in situations where:

1. Need to Create Families of Related Objects

When your system needs to handle multiple families of related or dependent objects without specifying their concrete classes. For example, a user interface toolkit that supports different themes (e.g., dark mode, light mode) might require different sets of components (buttons, text boxes) for each theme.

2. Product Variations

When you have multiple product variations that need to work together. If you need to ensure that all products in a family are compatible with each other, the Abstract Factory helps by providing a way to create these products in a cohesive manner.

3. Object Creation is Decoupled from Use

When you want to decouple the creation of objects from their use. The Abstract Factory provides an interface for creating objects, which allows the client code to remain independent of the concrete classes being instantiated.

4. System is Configured to Work with Multiple Product Families

When your system needs to support multiple product families, and you want to switch between these families easily. For example, a system that needs to support both Windows and Mac platforms with different sets of components can use Abstract Factory to manage these variations.

5. Consistency Among Related Products

When you need to ensure consistency among related products. The Abstract Factory guarantees that a set of related products are created together, ensuring that they fit together and work as intended.

Example Scenarios

1. User Interface Libraries

If you are developing a UI library that needs to work across different platforms (e.g., Windows, Mac, Linux), you can use the Abstract Factory to create platform-specific components (buttons, text boxes, menus) while ensuring they are consistent with each other.

public interface IUIFactory
{
    IButton CreateButton();
    ITextBox CreateTextBox();
}

public class WindowsFactory : IUIFactory
{
    public IButton CreateButton() => new WindowsButton();
    public ITextBox CreateTextBox() => new WindowsTextBox();
}

public class MacFactory : IUIFactory
{
    public IButton CreateButton() => new MacButton();
    public ITextBox CreateTextBox() => new MacTextBox();
}


2. Document Management Systems

For a document management system that supports multiple formats (e.g., PDF, Word), you can use Abstract Factory to create readers, editors, and savers for each document format.

public interface IDocumentFactory
{
    IReader CreateReader();
    IEditor CreateEditor();
    ISaver CreateSaver();
}

public class PdfDocumentFactory : IDocumentFactory
{
    public IReader CreateReader() => new PdfReader();
    public IEditor CreateEditor() => new PdfEditor();
    public ISaver CreateSaver() => new PdfSaver();
}

public class WordDocumentFactory : IDocumentFactory
{
    public IReader CreateReader() => new WordReader();
    public IEditor CreateEditor() => new WordEditor();
    public ISaver CreateSaver() => new WordSaver();
}

3. Game Development

In game development,if you need to create different sets of game objects (e.g., enemies, weapons) for different levels or settings, you can use Abstract Factory to manage these variations.

public interface IGameFactory
{
    IEnemy CreateEnemy();
    IWeapon CreateWeapon();
}

public class EasyLevelFactory : IGameFactory
{
    public IEnemy CreateEnemy() => new EasyEnemy();
    public IWeapon CreateWeapon() => new BasicWeapon();
}

public class HardLevelFactory : IGameFactory
{
    public IEnemy CreateEnemy() => new HardEnemy();
    public IWeapon CreateWeapon() => new AdvancedWeapon();
}

Summary

Use the Abstract Factory Design Pattern when:

  • You need to create families of related objects.
  • You want to ensure that objects from a family are used together.
  • Your system needs to support multiple product families and you want to keep your client code decoupled from concrete implementations.
  • You want to provide a consistent interface for creating related objects.

This pattern helps in managing complex object creation logic, ensuring consistency,

and providing flexibility in how objects are created and used. 


Differences between Abstract Factory and Factory Method Design Pattern

Differences between Abstract Factory and Factory Method Design Pattern

The Abstract Factory and Factory Method design patterns are both creational patterns used to create objects, but they differ in their structure and intent. Here are the key differences:

1. Intent

  • Factory Method: Defines an interface for creating a single product, but lets subclasses alter the type of product that will be created. The intention is to defer the instantiation of a class to subclasses.
  • Abstract Factory: Provides an interface for creating families of related or dependent products without specifying their concrete classes. The intention is to create a set of related products.

2. Structure

  • Factory Method: Typically involves a single method in a class to create an object. This pattern relies on inheritance: a base class defines the factory method, and derived classes implement the factory method to create specific products.

// Factory Method
public abstract class Creator
{
    public abstract IProduct FactoryMethod();
}

public class ConcreteCreator : Creator
{
    public override IProduct FactoryMethod()
    {
        return new ConcreteProduct();
    }
}


Abstract Factory: Involves multiple factory methods grouped into a single interface to create families of related products. This pattern relies on object composition: a factory class is responsible for creating products, and concrete factory classes implement the creation methods.

 // Abstract Factory

public interface IAbstractFactory
{
    IProductA CreateProductA();
    IProductB CreateProductB();
}

public class ConcreteFactory : IAbstractFactory
{
    public IProductA CreateProductA()
    {
        return new ConcreteProductA();
    }

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


3. Scope

  • Factory Method: Deals with the creation of a single product. Each factory method is responsible for creating a single type of product.
  • Abstract Factory: Deals with the creation of families of related products. An abstract factory groups related factory methods together, so you can create various related products through a single interface.

4. Usage

  • Factory Method: Used when a class cannot anticipate the class of objects it must create. It's useful when a class wants its subclasses to specify the object to be created.
  • Abstract Factory: Used when a system should be independent of how its products are created and composed. It's useful when a system needs to support multiple families of products.

5. Example in C#

Factory Method

// Product Interface
public interface IProduct
{
    void Operation();
}

// Concrete Product
public class ConcreteProduct : IProduct
{
    public void Operation()
    {
        Console.WriteLine("ConcreteProduct Operation");
    }
}

// Creator
public abstract class Creator
{
    public abstract IProduct FactoryMethod();

    public void AnOperation()
    {
        IProduct product = FactoryMethod();
        product.Operation();
    }
}

// Concrete Creator
public class ConcreteCreator : Creator
{
    public override IProduct FactoryMethod()
    {
        return new ConcreteProduct();
    }
}

// Usage
class Program
{
    static void Main(string[] args)
    {
        Creator creator = new ConcreteCreator();
        creator.AnOperation();
    }
}


Abstract Factory

// Abstract Products
public interface IProductA
{
    void OperationA();
}

public interface IProductB
{
    void OperationB();
}

// Concrete Products
public class ConcreteProductA1 : IProductA
{
    public void OperationA()
    {
        Console.WriteLine("ConcreteProductA1 OperationA");
    }
}

public class ConcreteProductB1 : IProductB
{
    public void OperationB()
    {
        Console.WriteLine("ConcreteProductB1 OperationB");
    }
}

// Abstract Factory
public interface IAbstractFactory
{
    IProductA CreateProductA();
    IProductB CreateProductB();
}

// Concrete Factory
public class ConcreteFactory1 : IAbstractFactory
{
    public IProductA CreateProductA()
    {
        return new ConcreteProductA1();
    }

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

// Usage
class Program
{
    static void Main(string[] args)
    {
        IAbstractFactory factory = new ConcreteFactory1();
        IProductA productA = factory.CreateProductA();
        IProductB productB = factory.CreateProductB();

        productA.OperationA();
        productB.OperationB();
    }
}

Summary

  • Factory Method is used for creating a single product and allows subclasses to determine the actual product to be created.
  • Abstract Factory is used for creating families of related products and provides a way to encapsulate a group of individual factories.

Each pattern has its own use case and choosing between them depends on the specific requirements of the software design.

👉👉👉When to use it Abstract Factory Design Pattern

Prototype Design Pattern in C# with Examples

Prototype Design Pattern in C# with Examples

In this article, we are going to discuss prototype design patterns in C#.

prototype design patterns are the creational design pattern.

As per the Gang of Four Definition: "Prototype Design Pattern Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype"

As per the prototype design pattern, we need to create an object once and can use it across the application, creating an object again and again in an application is an expensive and time-consuming task so as per this pattern once we create an object, we can utilize it wherever we need it.

  • reducing the complexity of the application to create the objects.
  • reduce the need to creating of an object again and again.
  • We can remove the object in runtime.

Prototype Design Pattern in C# 

below is an example of creating a prototype design pattern using the shallow copy method. here we are using the inbuild ICloneable interface.

public class Student: ICloneable
{
    public string Name { get; set; }
    public string Address { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public object Clone()
    {
        return this.MemberwiseClone();
    }
 
}
public class ProtoTypeDesignPattern
{
    static void Main(string[] args)
    {
        Student _student = new Student
        {
            Name = "dotnetOffice",
            Address = "XYZ",
            Age = 10,
            Gender = "Male"
        };

        Console.WriteLine($"Student Name:  {_student.Name}");

        Student cloneName = _student.Clone() as Student;
        Console.WriteLine($"Cloned Name:  {_student.Name}");

        cloneName.Name = "other name";
        Console.WriteLine($"origional name - {_student.Name}");
        Console.WriteLine($"Cloned Name - {cloneName.Name}");
    }
}

 

Fluent Interface Design Pattern in C# with Examples

Fluent Interface Design Pattern in C# with Examples


In this article, we will talk about the Fluent Interface Design Pattern in C# with examples. The Fluent Interface Design Pattern is a type of Creational Design Pattern.

Fluent Interface Design Pattern

The purpose of a fluent design pattern is to use multiple properties for the objects by connecting them with the .(dot) without giving the specifics of the object again.

A fluent interface design pattern is implemented by using the method cascading or concrete method chaining.

Implementation of Fluent Interface Design Pattern in C#
let's create a student class

public class Student
{

    public string Name { get; set; }

    public int Age { get; set; }

    public string Address { get; set; }

}

now let's assign values to student class

Student emp = new Student()
{

    Name  = "DotNet office",

    Age  = 12,

    Address  = "India"

};


What is Method Chaining?

Method chaining is the technique where each method returns an object and all of these methods can be chained together to create a single statement. to implement this, first, we need to create the wrapper class around the student class.

 public class StudentFluentExample


    {

        private Student obj = new Student();

        public StudentFluentExample NameOfTheStudent(string name)

        {

          obj.Name = name;

            return;

        }

        public StudentFluentExample Age(int age)

        {

            obj.Age = age;

            return;

        }

        public StudentFluentExample LivesIn(string address)

        {

            obj.Address = address;

            return;

        }

       

    }

now to access the above class methods we have to create an object of the class like below

as per fluent interfaces design pattern, we can access properties by connecting them with .(dot) like below
static void Main(string[] args)

        {
          StudentFluentExample obj = new StudentFluentExample();
          obj.NameOfTheStudent("Dotnet office").Age(12).LivesIn("India");

        }

uses of the Fluent Interface Design Pattern in C#
  1. Fluent code is more readable and allows us to vary a product's internal representation
  2. A fluent design pattern encapsulates the code for construction and representation and it Provides control over the steps of the object construction process.
  3. Sorting, Searching, and pagination using LINQ are some of the real-world examples of the fluent interface in the combination with the builder design pattern.


Builder Design Pattern in C# with Real-time Example in C#

Builder Design Pattern in C# with Real-time Example in C#

In this article, we will discuss the Builder Design Pattern in C# with models. it is part of the Creational Design Pattern.

Definition: "Separate the construction of a complex object from its representation so that the same construction process can create different representations"

Builder Design Pattern solves the situation of increasing constructor parameters and constructors of a given class by providing a step-by-step initialization of Parameters. After step-by-step initialization, it returns the resulting constructed object at once.

 

The Builder Design Pattern is a creational design pattern that allows you to create complex objects step by step. It separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

Here's a real-time example in C#: constructing a House object with various parts (walls, roof, etc.).

Step 1: Define the Product Class

public class House {

    public string Basement { get; set; }

    public string Structure { get; set; }

    public string Roof { get; set; }

    public string Interior { get; set; } 

public override string ToString()
{
    return $"House with Basement: {Basement}, Structure: {Structure}, Roof: {Roof}, Interior: {Interior}";
}
}

 

Step 2: Define the Builder Interface

public interface IHouseBuilder
{
     void BuildBasement();
     void BuildStructure();
     void BuildRoof();
     void BuildInterior();
     House GetHouse();
}

 

Step 3: Implement Concrete Builders

public class ConcreteHouseBuilder : IHouseBuilder
{
    private House _house = new House();

    public void BuildBasement()
    {
        _house.Basement = "Concrete Basement";
    }

    public void BuildStructure()
    {
        _house.Structure = "Concrete and Steel Structure";
    }

    public void BuildRoof()
    {
        _house.Roof = "Concrete Roof";
    }

    public void BuildInterior()
    {
        _house.Interior = "Painted Walls with Wooden Flooring";
    }

    public House GetHouse()
    {
        return _house;
    }
}

public class WoodenHouseBuilder : IHouseBuilder
{
    private House _house = new House();

    public void BuildBasement()
    {
        _house.Basement = "Wooden Basement";

    }

    public void BuildStructure()
    {
        _house.Structure = "Wood and Iron Structure";

    }

    public void BuildRoof()
    {
        _house.Roof = "Wooden Roof";
    }

    public void BuildInterior()
    {
        _house.Interior = "Wooden Walls with Carpet Flooring";
    }

    public House GetHouse()
    {
        return _house;
    }
}

 

Step 4: Define the Director Class

public class Director
{
    private IHouseBuilder _houseBuilder;

    public Director(IHouseBuilder houseBuilder)
    {
         _houseBuilder = houseBuilder;
    }

    public void ConstructHouse()
    {
        _houseBuilder.BuildBasement();
        _houseBuilder.BuildStructure();
        _houseBuilder.BuildRoof();
        _houseBuilder.BuildInterior();
    }

    public House GetHouse()
    {
        return _houseBuilder.GetHouse();
    }

}

 

Step 5: Use the Builder Pattern

class Program
{
    static void Main(string[] args)
    {
        IHouseBuilder concreteHouseBuilder = new ConcreteHouseBuilder();
        Director director = new Director(concreteHouseBuilder);
        director.ConstructHouse();
        House concreteHouse = director.GetHouse();
        Console.WriteLine(concreteHouse);

        IHouseBuilder woodenHouseBuilder = new WoodenHouseBuilder();
        director = new Director(woodenHouseBuilder);

        director.ConstructHouse();
        House woodenHouse = director.GetHouse();
        Console.WriteLine(woodenHouse);

    }

}

 

Explanation

  1. House: The product class, which has various parts such as Basement, Structure, Roof, and Interior.
  2. IHouseBuilder: The builder interface with methods to build different parts of the house and a method to get the final house object.
  3. ConcreteHouseBuilder and WoodenHouseBuilder: Concrete builder classes that implement the IHouseBuilder interface to build a concrete house and a wooden house, respectively.
  4. Director: The director class that constructs a house using the builder interface.
  5. Program: The client code that uses the builder pattern to create different types of houses.

This example shows how the Builder Design Pattern can be used to construct complex objects with a step-by-step approach, ensuring the same construction process can produce different representations of the object.