Thursday, July 13, 2023

The Builder design pattern using C#

The Builder design pattern using C#

The Builder pattern is a creational design pattern that lets you construct complex objects step by step. It separates the construction of an object from its representation so that the same construction process can create different representations. It's particularly useful when you need to create an object with lots of possible configuration options. The Builder design pattern is used when there is a need to construct complex objects step by step. It separates the construction of an object from its representation. By doing this, the same construction process can create different representations. Here, we'll use the Builder design pattern to construct a Monster object.
Let's break it down into different .cs files: we start with IMonster is the interface that outlines necessary steps for building a Monster object.
public interface IMonster
{
    void SetName(string name);
    void SetCatchPhase(string phrase);
    void SetHeadType(string type);
       
    Monster GetMonster();
}
The Monster class is the complex object that is being built.
public class Monster
{
    public string Name { get; set; }
    public string CatchPhrase { get; set; }
    public string HeadType { get; set; }
        
    public void Describe()
    {
        Console.WriteLine($"Monster name is {Name} he says {CatchPhrase} and his head type is {HeadType}");
    }
}
MonsterBuilder
public class MonsterBuilder : IMonster
{
    private Monster _monster = new Monster();
        
    public void SetName(string name)
    {
        _monster.Name = name;
    }

    public void SetCatchPhase(string phrase)
    {
        _monster.CatchPhrase = phrase;
    }

    public void SetHeadType(string type)
    {
        _monster.HeadType = type;
    }

    public Monster GetMonster()
    {
        return _monster;
    }
}
The DrFrankenstein class defines the order in which to execute the building steps.
public class DrFrankenstein
{
    public void Construct(IMonster monster)
    {
        monster.SetName("Frank");
        monster.SetCatchPhase("They did the monster mash");
        monster.SetHeadType("flat");
    }
}
We goto the Main in Program.cs
public static void Main(string[] args)
{
    DrFrankenstein drFrank = new DrFrankenstein();
    MonsterBuilder igor = new MonsterBuilder();
        
    // Director uses the builder to construct the object
    drFrank.Construct(igor);
        
    Monster monster = igor.GetMonster();
        
    monster.Describe();
}
When we comile and run we get
Monster name is Frank he says They did the monster mash and his head type is flat
You would use the Builder pattern when: The object creation process should be independent from the parts that make up the object. The construction process should allow different representations for the object that's constructed. The object has many potential configurations, or when increasing the number of constructor parameters would result in an explosion of constructors. In our case, a monster can have various types of bodies, different names, and power levels, and we want to avoid creating a new constructor for each combination. This is where the Builder pattern becomes useful.

Tuesday, July 04, 2023

Abstract Factory pattern in C++

In our example, the Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. In our case, we will create a UIFactory that can create a Button and Scrollbar objects, and well also create the WindowsUIFactory and MacUIFactory
#include "Button.h"
#include "Scrollbar.h"
class UIFactory { 
public:
    virtual Button* createButton() = 0;
    virtual Scrollbar* createScrollbar() = 0;
};
This is the abstract factory class. It provides an interface to create objects of Button and Scrollbar types. It declares two pure virtual methods: createButton and createScrollbar. For Button object
class Button {
public:
    virtual void click() = 0;
};
For ScrollBar object
class Scrollbar { 
public:
    virtual void scroll() = 0;
};
Button and Scrollbar classes: These are abstract product classes. Each of them declares a pure virtual function (click() for Button and scroll() for Scrollbar) to be overridden in derived classes. So let's start with creating a WindowsUIFactory
#include "UIFactory.h"
#include "WindowsButton.h"
#include "WindowsScrollbar.h"

class WindowsUIFactory : public UIFactory {  
public:
    Button* createButton() override {
        return new WindowsButton();
    }

    Scrollbar* createScrollbar() override {
        return new WindowsScrollbar();
    }
};
This is a concrete factory class. It implements the UIFactory interface and overrides the createButton and createScrollbar methods to create Windows-specific objects (WindowsButton and WindowsScrollbar). For the WindowsButton
class WindowsButton : public Button{ 
public:
    void click() override {
        std::cout << "WindowsButton scroll." << std::endl;
    }
};
... and for the WindowsScrollbar,
#include 
#include "Scrollbar.h"

class WindowsScrollbar : public Scrollbar{ 
public:
    void scroll() override {
        std::cout << "WindowsScrollbar scroll." << std::endl;
    }
};
WindowsButton and WindowsScrollbar classes: These are concrete product classes. They implement the Button and Scrollbar interfaces respectively and override their virtual functions. Now let's look at the Mac side so we have the MacUIFactory.
#include "UIFactory.h"
#include "MacButton.h"
#include "MacScrollbar.h"

class MacUIFactory : public UIFactory { 
public:
Button* createButton() override {
    return new MacButton();
}
 Scrollbar* createScrollbar() override {
    return new MacScrollbar();
}
};
Similar to WindowsUIFactory, this is a concrete factory that creates Mac-specific objects (MacButton and MacScrollbar). For the MacButton,
#include 
#include "Button.h"

class  MacButton : public Button { 
public:
    void click() override {
        std::cout << "MacButton click." << std::endl;
    }
};
Like the Windows counterparts, these are concrete product classes for Mac that implement Button and Scrollbar interfaces respectively. and the MacScrollbar
#include 
#include "Scrollbar.h"

class MacScrollbar : public Scrollbar{  
public:
    void scroll() override {
        std::cout << "MacScrollbar scroll." << std::endl;
    }
};
now let's but these together in main:
#include <<iostream>

#include "UIFactory.h"
#include "WindowsUIFactory.h"
#include "MacUIFactory.h"

int main() {
    UIFactory* factory;

// Use WindowsUIFactory
    factory = new WindowsUIFactory();
    Button* windowsButton = factory->createButton();
    windowsButton->click();
    Scrollbar* windowsScrollbar = factory->createScrollbar();
    windowsScrollbar->scroll();
    delete windowsButton;
    delete windowsScrollbar;
    delete factory;

// Use MacUIFactory
    factory = new MacUIFactory();
    Button* macButton = factory->createButton();
    macButton->click();
    Scrollbar* macScrollbar = factory->createScrollbar();
    macScrollbar->scroll();
    delete macButton;
    delete macScrollbar;
    delete factory;
    return 0;
}
In the main() function:
WindowsButton scroll.
WindowsScrollbar scroll.
MacButton click.
MacScrollbar scroll.
We instantiate the specific UIFactory (Windows or Mac), and then use it to create the Button and Scrollbar objects. This demonstrates the benefit of the Abstract Factory pattern: the client code (here main()) works with abstract interfaces (UIFactory, Button, Scrollbar) and is agnostic to the concrete classes. We use the factory to create the concrete Button and Scrollbar objects and invoke their actions. After usage, the objects are deleted to free up memory resources. When we compile and run we get:
WindowsButton CLICK!!.
WindowsScrollbar is scrolling.
MacButton clicked.
MacScrollbar scrolled.
When the code is executed, depending on the UIFactory used, you get the corresponding Button and Scrollbar actions. This abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes. It allows for new types of themes to be easily incorporated with minimal changes to the client code.
>
TheRayCode.org
RayAndrade.com
Facebook
YouTube

The Strategy Design Pattern a Behavioral Pattern using C++

The Strategy Design Pattern is a behavioral design pattern that enables selecting an algorithm's implementation at runtime. Instead of i...