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