Courses/Java/OOP Design Patterns

    Lesson 16 โ€ข Advanced

    OOP Design Patterns

    Apply Singleton, Factory, Builder, and Decorator patterns to write professional Java code.

    ๐Ÿ“š Before You Start

    You should be comfortable with:

    • OOP & Inheritance (Lessons 9-10) โ€” classes, polymorphism, extending
    • Interfaces (Lesson 11) โ€” contracts and implementations
    • Advanced Methods (Lesson 15) โ€” method references, lambdas

    What You'll Learn

    • โœ… Singleton pattern โ€” ensure only one instance exists
    • โœ… Factory pattern โ€” create objects without exposing logic
    • โœ… Builder pattern โ€” construct complex objects step by step
    • โœ… Decorator pattern โ€” add behaviour dynamically
    • โœ… Observer pattern โ€” event-driven communication
    • โœ… When to use each pattern in real projects

    1๏ธโƒฃ Why Design Patterns?

    Design patterns are proven solutions to common software design problems. They were popularized by the "Gang of Four" book and remain the lingua franca of professional developers.

    ๐Ÿ’ก Real-World Analogy: Design patterns are like architectural blueprints. A Singleton is like having one CEO. A Factory is like a car assembly line. A Builder is like ordering a custom pizza. A Decorator is like gift-wrapping โ€” adding layers without changing the gift.

    Three categories: Creational (Singleton, Factory, Builder) manage object creation. Structural (Decorator, Adapter) manage composition. Behavioral (Observer, Strategy) manage communication.

    2๏ธโƒฃ Singleton & Factory Patterns

    Singleton: Ensures only one instance of a class exists. Perfect for database connections, configuration managers, and caches.

    // Thread-safe Singleton (enum approach)
    public enum Database {
        INSTANCE;
        public void connect() { /* ... */ }
    }
    // Usage: Database.INSTANCE.connect();

    Factory: Creates objects without exposing creation logic. The caller asks for a product by type and gets the right subclass back.

    public class AnimalFactory {
        public static Animal create(String type) {
            return switch (type) {
                case "dog" -> new Dog();
                case "cat" -> new Cat();
                default -> throw new IllegalArgumentException("Unknown: " + type);
            };
        }
    }

    Try It: Singleton & Factory Patterns

    Build a database singleton and an animal factory

    Try it Yourself ยป
    JavaScript
    // ๐Ÿ’ก Try modifying this code and see what happens!
    // Singleton & Factory Patterns (Simulated)
    console.log("=== Singleton Pattern ===\n");
    
    class Database {
        static instance = null;
        constructor(name) {
            if (Database.instance) return Database.instance;
            this.name = name;
            this.connections = 0;
            Database.instance = this;
        }
        connect() {
            this.connections++;
            console.log("  Connected to " + this.name + " (conn #" + this.connections + ")");
       
    ...

    3๏ธโƒฃ Builder Pattern

    The Builder pattern constructs complex objects step by step using method chaining. Each method returns this so calls can be chained fluently.

    User user = new User.Builder("Alice")
        .email("alice@mail.com")
        .age(25)
        .role("admin")
        .build();

    When to use: Objects with many optional parameters, SQL query construction, configuration objects, or any case where a constructor with 10+ params would be confusing.

    Try It: Builder & Decorator Patterns

    Build SQL queries with Builder and wrap coffee orders with Decorator

    Try it Yourself ยป
    JavaScript
    // ๐Ÿ’ก Try modifying this code and see what happens!
    // Builder & Decorator Patterns (Simulated)
    console.log("=== Builder Pattern ===\n");
    
    class QueryBuilder {
        constructor() { this.parts = { table: "", conditions: [], columns: "*", limit: null, orderBy: null }; }
        from(table) { this.parts.table = table; return this; }
        select(cols) { this.parts.columns = cols; return this; }
        where(cond) { this.parts.conditions.push(cond); return this; }
        orderBy(col) { this.parts.orderBy = col; 
    ...

    4๏ธโƒฃ Observer Pattern

    Analogy: Like a newsletter subscription โ€” you subscribe once, and whenever there's news, you get notified automatically. No need to keep checking.

    // Java: PropertyChangeListener, Observer pattern
    subject.addObserver(observer);
    subject.notifyAll(event);

    Try It: Observer Pattern & Event System

    Build a publish-subscribe event system for notifications

    Try it Yourself ยป
    JavaScript
    // ๐Ÿ’ก Try modifying this code and see what happens!
    // Observer Pattern (Simulated)
    console.log("=== Observer Pattern ===\n");
    
    class EventEmitter {
        constructor() { this.listeners = {}; }
        on(event, callback) {
            if (!this.listeners[event]) this.listeners[event] = [];
            this.listeners[event].push(callback);
            return this; // allow chaining
        }
        off(event, callback) {
            if (this.listeners[event]) {
                this.listeners[event] = this.listeners[event].filte
    ...

    5๏ธโƒฃ Common Mistakes

    โŒ
    Singleton not thread-safe: Use enum singleton or double-checked locking.
    โŒ
    Overusing patterns: Not every class needs a Factory. Use patterns when they solve a real problem.
    โŒ
    Builder without validation: Always validate in build() โ€” invalid objects defeat the purpose.
    โŒ
    God Observer: One event emitter handling everything becomes unmaintainable. Use domain-specific channels.

    6๏ธโƒฃ Pro Tips

    ๐Ÿ’ก Enum Singleton is the safest in Java โ€” thread-safe, serialization-safe, reflection-proof.

    ๐Ÿ’ก Builder + immutable objects is a powerful combo. Make all fields final and only settable through the builder.

    ๐Ÿ’ก In interviews, knowing when NOT to use a pattern is more impressive than knowing the pattern itself.

    ๐Ÿ“‹ Quick Reference

    PatternPurposeWhen to Use
    SingletonOne instance onlyDatabase, config, cache
    FactoryCreate without exposing logicObject families, plugins
    BuilderStep-by-step constructionComplex objects, queries
    DecoratorAdd behavior dynamicallyWrapping, middleware
    ObserverEvent notificationUI events, messaging

    ๐ŸŽ‰ Lesson Complete!

    You now understand the most important OOP design patterns used in enterprise Java development!

    Next: Interfaces, Abstraction & Best Practices โ€” default methods, sealed interfaces, and interface-first design.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy Policy โ€ข Terms of Service