# Design Patterns for Beginners — Singleton, Factory, Observer, Strategy

Source: https://skills101.in/learn/oops/design-patterns-basics — Skills101 free tutorial (OOP Concepts). Updated 2026-11-09.

A **design pattern** is a named, proven solution to a problem that keeps coming up in software design. Knowing a few patterns helps you write better code and talk clearly with senior developers.

![Four pattern cards: Singleton (exactly one instance), Factory (a method decides which class to create), Observer (subscribers notified on change) and Strategy (swap an algorithm at runtime)](https://skills101.in/learn-img/oops/patterns.svg)

Patterns are grouped as **creational** (how objects are made), **structural** (how they're combined) and **behavioural** (how they communicate).

## 1. Singleton (creational)

**Problem:** some things must exist **only once** — app configuration, a logger, a connection pool.

```java
class AppConfig {
    private static AppConfig instance;
    private final String env;
    private AppConfig() { env = "production"; }        // private: no one else can call new
    static synchronized AppConfig get() {
        if (instance == null) instance = new AppConfig();
        return instance;
    }
    String env() { return env; }
}

public class Main {
    public static void main(String[] args) {
        AppConfig a = AppConfig.get(), b = AppConfig.get();
        System.out.println((a == b) + " " + a.env());
    }
}
```

```text
true production
```

Use sparingly: singletons are global state and make testing harder.

## 2. Factory (creational)

**Problem:** the code shouldn't need to know **which class** to create — a factory decides.

```python
class Upi:
    def pay(self, amt): return f"UPI ₹{amt}"
class Card:
    def pay(self, amt): return f"Card ₹{amt}"
class NetBanking:
    def pay(self, amt): return f"NetBanking ₹{amt}"

def payment_factory(mode):
    methods = {"upi": Upi, "card": Card, "netbanking": NetBanking}
    if mode not in methods:
        raise ValueError(f"unknown payment mode: {mode}")
    return methods[mode]()

for mode in ["upi", "card"]:
    print(payment_factory(mode).pay(999))
```

```text
UPI ₹999
Card ₹999
```

Seen in: `Calendar.getInstance()`, database drivers, UI toolkits.

## 3. Observer (behavioural)

**Problem:** when something changes, many others must be **notified** — without the source knowing them all in advance.

```python
class Channel:
    def __init__(self, name):
        self.name, self.subscribers = name, []
    def subscribe(self, fn):
        self.subscribers.append(fn)
    def publish(self, video):
        for notify in self.subscribers:
            notify(f"{self.name} uploaded: {video}")

ch = Channel("Skills101")
ch.subscribe(lambda msg: print("Asha's phone →", msg))
ch.subscribe(lambda msg: print("Ravi's email →", msg))
ch.publish("SQL Joins in 10 minutes")
```

```text
Asha's phone → Skills101 uploaded: SQL Joins in 10 minutes
Ravi's email → Skills101 uploaded: SQL Joins in 10 minutes
```

Seen in: YouTube notifications, button click listeners, event systems.

## 4. Strategy (behavioural)

**Problem:** you need **interchangeable algorithms** chosen at runtime (delivery fee rules, sorting methods, payment routes).

```python
def standard(km): return 30 + 5 * km
def express(km): return 60 + 8 * km
def free_above_499(km): return 0

class Checkout:
    def __init__(self, fee_strategy):
        self.fee = fee_strategy
    def total(self, cart, km):
        return cart + self.fee(km)

print(Checkout(standard).total(350, 4), Checkout(express).total(350, 4), Checkout(free_above_499).total(650, 4))
```

```text
400 442 650
```

Strategy replaces long `if/else` chains with plug-in objects or functions.

## Other names worth recognising

| Pattern | One line |
|---|---|
| **Builder** | build a complex object step by step (`StringBuilder`, `Request.builder()`) |
| **Adapter** | make one interface fit another (a charger adapter) |
| **Decorator** | add behaviour by wrapping (Java I/O streams, Python `@decorators`) |
| **MVC** | separate Model, View and Controller in web apps |

## Common mistakes

- Using patterns everywhere to look clever. Use one when its **problem** actually appears.
- Singleton without thread safety in multi-threaded code.

## Quick recap

- Singleton: one instance. Factory: decide which class to create.
- Observer: notify subscribers on change. Strategy: swap algorithms at runtime.
- Patterns are shared vocabulary for common design problems.


Practice quiz and free certificate: https://skills101.in/learn/oops/design-patterns-basics