Skip to main content

Command Palette

Search for a command to run...

Design Patterns in Java

Published
β€’6 min readβ€’View as Markdown
ChatGPT said:

Excellent πŸ”₯ β€” this is one of the most important and interview-focused topics for both Java developers and automation testers.

Let’s go step-by-step β€”
I’ll cover every Design Pattern with:

  • βœ… Concept

  • βœ… Real-world example

  • βœ… Java code example

  • βœ… Usage in Automation Frameworks (Selenium/TestNG/Maven/Jenkins)


🎯 What are Design Patterns?

πŸ‘‰ Design patterns are proven templates or reusable solutions to common software design problems.
They make code more maintainable, reusable, and readable.

They are broadly divided into 3 categories:
1️⃣ Creational Patterns
2️⃣ Structural Patterns
3️⃣ Behavioral Patterns


🧱 1️⃣ Creational Design Patterns

Used for object creation β€” controlling how and when objects are created.

PatternPurposeExampleUsage in Automation

1. Singleton Pattern

πŸ‘‰ Ensures that only one instance of a class is created in the JVM.

Real-life example:
There can be only one driver instance in Selenium tests.

Java Example:

public class DriverManager {
    private static WebDriver driver;

    private DriverManager() {} // private constructor

    public static WebDriver getDriver() {
        if (driver == null) {
            driver = new ChromeDriver();
        }
        return driver;
    }
}

In Automation:
Used for:

  • WebDriver instance management

  • Property file readers

  • Database connections


2. Factory Pattern

πŸ‘‰ Provides a way to create objects without exposing creation logic.

Real-life example:
Different browser drivers (Chrome, Edge, Firefox) β€” one factory decides which to use.

Java Example:

public class WebDriverFactory {
    public static WebDriver getDriver(String browser) {
        if (browser.equalsIgnoreCase("chrome"))
            return new ChromeDriver();
        else if (browser.equalsIgnoreCase("firefox"))
            return new FirefoxDriver();
        else
            throw new IllegalArgumentException("Invalid browser");
    }
}

In Automation:
Used for:

  • Creating browser drivers

  • Page object initialization

  • Environment-based object creation


3. Builder Pattern

πŸ‘‰ Builds complex objects step by step.

Real-life example:
Building a test data object with multiple optional fields.

Java Example:

public class User {
    private String name;
    private int age;
    private String email;

    private User(UserBuilder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.email = builder.email;
    }

    public static class UserBuilder {
        private String name;
        private int age;
        private String email;

        public UserBuilder setName(String name) { this.name = name; return this; }
        public UserBuilder setAge(int age) { this.age = age; return this; }
        public UserBuilder setEmail(String email) { this.email = email; return this; }

        public User build() {
            return new User(this);
        }
    }
}

In Automation:
Used for:

  • Creating dynamic test data

  • Configuring test objects (like Request payloads in API testing)


4. Prototype Pattern

πŸ‘‰ Clones existing objects instead of creating new ones.

Real-life example:
Duplicating similar test data objects without reconstructing.

Java Example:

public class TestData implements Cloneable {
    public String username;
    public String password;

    public TestData(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public TestData clone() throws CloneNotSupportedException {
        return (TestData) super.clone();
    }
}

In Automation:
Used when:

  • You need multiple similar test data sets or configurations quickly.

5. Abstract Factory Pattern

πŸ‘‰ Factory of factories β€” produces families of related objects.

Real-life example:
Creating drivers and capabilities for different environments (Web, Mobile).

In Automation:
Used in cross-platform frameworks (Web + Mobile + API) to produce environment-specific instances.


🧩 2️⃣ Structural Design Patterns

Used to organize and connect classes and objects.

PatternPurposeExampleUsage in Automation

6. Adapter Pattern

πŸ‘‰ Converts one interface into another expected by the client.

Real-life example:
USB-to-Type-C converter.

Java Example:

interface WebDriver {
    void getElement();
}

class ChromeDriverImpl implements WebDriver {
    public void getElement() { System.out.println("Chrome element"); }
}

class SafariDriverAdapter implements WebDriver {
    private SafariDriver safari;

    public SafariDriverAdapter(SafariDriver safari) {
        this.safari = safari;
    }

    public void getElement() {
        safari.findElement(); // adapting SafariDriver’s method
    }
}

In Automation:
Used for:

  • Integrating APIs or libraries with different interfaces

  • Handling multiple browser or device drivers uniformly


7. Decorator Pattern

πŸ‘‰ Adds new functionality to an object without modifying its structure.

Real-life example:
Adding extra toppings on a pizza.

Java Example:

interface WebPage {
    void display();
}

class BasicPage implements WebPage {
    public void display() { System.out.println("Displaying basic page"); }
}

class AuthenticatedPage implements WebPage {
    private WebPage page;

    public AuthenticatedPage(WebPage page) {
        this.page = page;
    }

    public void display() {
        page.display();
        System.out.println("Adding authentication check");
    }
}

In Automation:
Used for:

  • Adding logging, reporting, or screenshots without changing test logic

8. Proxy Pattern

πŸ‘‰ Provides a surrogate object to control access to another object.

Real-life example:
Security proxy controlling access to a server.

In Automation:
Used for:

  • Lazy WebDriver initialization

  • API mocking or intercepting requests


9. Facade Pattern

πŸ‘‰ Simplifies complex subsystems by providing a unified interface.

Real-life example:
Remote control operates complex devices.

Java Example:

class TestExecutionFacade {
    public void executeTestSuite() {
        new Setup().init();
        new RunTests().start();
        new Report().generate();
    }
}

In Automation:
Used for:

  • Hiding complex framework layers behind a simple method like runTests()

10. Composite Pattern

πŸ‘‰ Treats individual objects and groups uniformly.

In Automation:
Used in Page Object Models where multiple web elements form a component.


βš™οΈ 3️⃣ Behavioral Design Patterns

Focus on communication between objects.

PatternPurposeExampleUsage in Automation

11. Strategy Pattern

πŸ‘‰ Defines a family of algorithms and lets you choose at runtime.

Real-life example:
Choosing payment method (UPI, Card, Cash).

Java Example:

interface BrowserStrategy { void openBrowser(); }

class ChromeStrategy implements BrowserStrategy {
    public void openBrowser() { System.out.println("Chrome Opened"); }
}

class FirefoxStrategy implements BrowserStrategy {
    public void openBrowser() { System.out.println("Firefox Opened"); }
}

class BrowserContext {
    private BrowserStrategy strategy;
    public void setStrategy(BrowserStrategy strategy) { this.strategy = strategy; }
    public void execute() { strategy.openBrowser(); }
}

In Automation:
Used for:

  • Switching browser, environment, or reporting tools dynamically.

12. Observer Pattern

πŸ‘‰ When one object changes, all its dependents get notified.

Real-life example:
Email notification after a test fails.

In Automation:
Used in:

  • TestNG listeners

  • Event-driven frameworks (on test pass/fail, send report)


13. Command Pattern

πŸ‘‰ Encapsulates requests as objects.

Real-life example:
Undo/Redo operations.

In Automation:
Used for:

  • Executing a series of test steps or API calls dynamically

14. Template Method Pattern

πŸ‘‰ Defines skeleton of an algorithm but lets subclasses fill in the details.

In Automation:
Used in TestNG base classes:

@BeforeMethod β†’ setup()
@Test β†’ runTest()
@AfterMethod β†’ tearDown()

Framework defines structure; test class defines details.


15. Chain of Responsibility Pattern

πŸ‘‰ Passes a request along a chain of handlers until one handles it.

Real-life example:
Support escalation (L1 β†’ L2 β†’ L3).

In Automation:
Used for:

  • Handling multiple types of exceptions

  • Validation flows in input data


🧾 Summary Table

CategoryDesign PatternUsed In Framework
CreationalSingletonWebDriver, ConfigReader
CreationalFactoryBrowserFactory, DriverFactory
StructuralFacadeTestExecutionManager
StructuralAdapterCross-platform drivers
StructuralDecoratorLogging, Reporting
BehavioralStrategyBrowser/Environment selection
BehavioralObserverTestNG Listeners, EventFiringWebDriver
BehavioralTemplateBaseTest setup/teardown
BehavioralChain of ResponsibilityException handling

βœ… In Automation Frameworks:

  • Singleton β†’ One WebDriver instance

  • Factory β†’ Create drivers/environments

  • Builder β†’ Build payloads or data

  • Strategy β†’ Run tests on multiple browsers

  • Observer β†’ Reporting (listeners)

  • Decorator β†’ Logging/screenshots

  • Facade β†’ Simplified framework execution

  • Template β†’ Base test classes