Monday, March 2, 2026

Structural Patterns

 

Structural patterns focus on how classes and objects are composed to form larger structures.

1) Adapter Pattern

Converts one interface into another expected interface.

Example

Old printer class does not match new interface.

// Target interface
public interface IPrinter
{
    void Print();
}

// Existing class (incompatible)
public class OldPrinter
{
    public void PrintOld()
    {
        Console.WriteLine("Printing from Old Printer");
    }
}

// Adapter
public class PrinterAdapter : IPrinter
{
    private OldPrinter _oldPrinter = new OldPrinter();

    public void Print()
    {
        _oldPrinter.PrintOld();
    }
}

// Usage
IPrinter printer = new PrinterAdapter();
printer.Print();

2) Bridge Pattern

Separates abstraction from implementation.

Example

Remote control working with different TVs.

public interface ITV
{
    void On();
}

public class SonyTV : ITV
{
    public void On()
    {
        Console.WriteLine("Sony TV ON");
    }
}

public class SamsungTV : ITV
{
    public void On()
    {
        Console.WriteLine("Samsung TV ON");
    }
}

public class Remote
{
    protected ITV _tv;

    public Remote(ITV tv)
    {
        _tv = tv;
    }

    public void TurnOn()
    {
        _tv.On();
    }
}

// Usage
Remote remote = new Remote(new SonyTV());
remote.TurnOn();

3) Composite Pattern

Treats individual objects and groups of objects uniformly.

Example

File and Folder structure.

public interface IFileSystem
{
    void Show();
}

public class File : IFileSystem
{
    public void Show()
    {
        Console.WriteLine("File");
    }
}

public class Folder : IFileSystem
{
    private List<IFileSystem> _items = new List<IFileSystem>();

    public void Add(IFileSystem item)
    {
        _items.Add(item);
    }

    public void Show()
    {
        Console.WriteLine("Folder:");
        foreach (var item in _items)
        {
            item.Show();
        }
    }
}

// Usage
Folder folder = new Folder();
folder.Add(new File());
folder.Add(new File());
folder.Show();

4) Decorator Pattern

Adds new behavior to an object dynamically.

Example

Adding extra features to coffee.

public interface ICoffee
{
    string GetDescription();
}

public class SimpleCoffee : ICoffee
{
    public string GetDescription()
    {
        return "Plain Coffee";
    }
}

public class MilkDecorator : ICoffee
{
    private ICoffee _coffee;

    public MilkDecorator(ICoffee coffee)
    {
        _coffee = coffee;
    }

    public string GetDescription()
    {
        return _coffee.GetDescription() + " + Milk";
    }
}

// Usage
ICoffee coffee = new MilkDecorator(new SimpleCoffee());
Console.WriteLine(coffee.GetDescription());

5) Facade Pattern

Provides simplified interface to a complex system.

Example

public class CPU
{
    public void Start() => Console.WriteLine("CPU Started");
}

public class Memory
{
    public void Load() => Console.WriteLine("Memory Loaded");
}

public class ComputerFacade
{
    private CPU _cpu = new CPU();
    private Memory _memory = new Memory();

    public void StartComputer()
    {
        _cpu.Start();
        _memory.Load();
        Console.WriteLine("Computer Ready");
    }
}

// Usage
ComputerFacade computer = new ComputerFacade();
computer.StartComputer();

6) Flyweight Pattern

Reduces memory usage by sharing common objects.

Example

public class Circle
{
    public string Color { get; set; }

    public Circle(string color)
    {
        Color = color;
    }

    public void Draw()
    {
        Console.WriteLine("Drawing " + Color + " circle");
    }
}

Instead of creating many same-color objects, reuse existing ones.


7) Proxy Pattern

Controls access to another object.

Example

public interface IImage
{
    void Display();
}

public class RealImage : IImage
{
    public RealImage()
    {
        Console.WriteLine("Loading Image...");
    }

    public void Display()
    {
        Console.WriteLine("Displaying Image");
    }
}

public class ProxyImage : IImage
{
    private RealImage _realImage;

    public void Display()
    {
        if (_realImage == null)
            _realImage = new RealImage();

        _realImage.Display();
    }
}

// Usage
IImage image = new ProxyImage();
image.Display();

Summary (Simple Understanding)

Adapter → Converts interface
Bridge → Separates abstraction & implementation
Composite → Tree structure (part-whole)
Decorator → Adds extra behavior
Facade → Simplifies complex system
Flyweight → Shares objects to save memory
Proxy → Controls access