0% found this document useful (0 votes)
3 views32 pages

Understanding Singleton Design Pattern

The document provides an overview of design patterns, specifically focusing on the Singleton pattern, which ensures a class has only one instance and provides a global access point to it. It discusses the importance of design patterns for reusability, scalability, and maintainability, and outlines various types of design patterns, including creational patterns like Singleton. Additionally, it details the implementation, use cases, and potential pitfalls of the Singleton pattern, along with guidelines for effective use.

Uploaded by

nkp919293
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views32 pages

Understanding Singleton Design Pattern

The document provides an overview of design patterns, specifically focusing on the Singleton pattern, which ensures a class has only one instance and provides a global access point to it. It discusses the importance of design patterns for reusability, scalability, and maintainability, and outlines various types of design patterns, including creational patterns like Singleton. Additionally, it details the implementation, use cases, and potential pitfalls of the Singleton pattern, along with guidelines for effective use.

Uploaded by

nkp919293
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Design Pattern [Link]

com/design-pattern

Appearance Add new Edit this post Nitesh Synergy

Design Pattern
Welcome To Design Pattern Blog By Nitesh Synergy

✅ What is a Design Pattern?


A design pattern is a proven, reusable solution to a common
problem in software design. It is not a complete code, but a
template or guideline on how to solve specific design issues
in object-oriented software.

Think of design patterns like blueprints—software


architects use them to build robust, maintainable, and
scalable applications.

Why Are Design Patterns Needed?


1. Reusability – Save time by using tried-and-tested
solutions.
2. Scalability – Help build flexible, easily
extendable code.
3. Maintainability – Code becomes easier to
understand and update.
4. Standardization – Brings a common vocabulary for
developers.
5. Avoid Re-inventing the Wheel – Use known solutions
for known problems.

Types of Design Patterns


Design patterns are broadly classified into 3 main
categories:

1. Creational Patterns
(Object creation)
Used when object creation is complex or needs to be
controlled.

1 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance PatteEdit
Add new rn this
Nam e
post Purpose Nitesh Synergy

Singleton Only one instance of a class.

Factory Create objects without exposing the


Method exact class.

Abstract
Factory of related factories.
Factory

Builder Step-by-step object creation.

Prototype Clone existing objects.

1. Singleton Pattern

✅ What is Singleton Pattern?


Singleton is a creational design pattern that ensures:

• Only one instance of a class exists throughout the


application.
• Provides a global point of access to that
instance.

✅ Why Singleton is Important?


• Resource Control: Controls access to resources
like DB connections, configuration files, or
loggers.
• Memory Efficiency: Avoids creation of multiple
objects of the same class unnecessarily.
• Consistency: Ensures consistent state/data across
the system.

✅ When to Use Singleton? (Use Cases)


Use Singleton when:

1. Single Configuration Across App


• E.g., App-wide configuration manager or
settings file.
2. Database Connection Pool
• Only one connection manager instance to handle
all DB operations.
3. Logging
• Centralized logger instance to log from any
part of the app.
4. Caching
• Central cache store used throughout
application.
5. Thread Pool

• Single pool used by multiple threads.

2 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy

✅ Real-Time Project Example

🔹 Project: E-commerce
Application
• Singleton Use:
◦ A Logger class logs order activity, errors,
payments.
◦ DatabaseConnector class manages connections to
the MySQL DB.
◦ AppConfig class loads settings like tax %,
currencies, and uses it across services.

When Not to Use Singleton


Avoid Singleton when:

1. Unit Testing Needed


• Singleton hides dependencies, making mocking
hard.
2. Multi-threading if not handled properly
• Poor implementation can lead to race
conditions.
3. Global State is a Problem
• Leads to tight coupling between classes.
4. Requires Multiple Instances
• E.g., Different connections for different
databases.

Rules For Singleton Pattern:

1. Private Constructor
Ensure the class constructor is private to prevent
instantiation from outside the class.

2. Static Instance Variable


Create a static (ideally final ) variable to hold the single
instance of the class.

3. Global Access Point


Provide a public static method or property that returns the
same instance every time it's called.

4. Thread Safety

3 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

In multithreaded environments, ensure that the instance


Appearance Add new Edit this post Nitesh Synergy
creation logic is thread-safe to avoid multiple instances
being created.

5. Prevent Cloning
Override the cloning behavior to avoid duplication of the
singleton object via clone() .

6. Serialization Safety
Implement mechanisms (like readResolve() in Java) to prevent
deserialization from creating a new instance.

7. Reflection Safety
Add checks inside the constructor to throw an exception if an
instance already exists, thus protecting against reflection-
based instantiation.

8. Static Block for Eager


Initialization
Use a static block to eagerly initialize the singleton and
include logic to prevent reflection-based violations if
needed.

9. Use of final Keyword


Mark the instance variable as final to ensure immutability
and prevent reassignment after initialization.

Guidelines for Using Singleton


• Use Only When Necessary: Singleton introduces
global state — use it only when a single instance
is essential (e.g., config, logging).
• Avoid Overuse: Overuse leads to tight coupling and
makes testing harder.
• Ensure Thread Safety: Always ensure thread-safe
implementation in concurrent environments.
• Testing Considerations: Mock singleton objects
during unit testing to isolate dependencies.
• Lazy vs Eager Initialization:
◦ Use lazy initialization when the object is
heavy and not always needed.
◦ Use eager initialization when the object is
lightweight or always needed.

4 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

✅WWays To Achieve Singleton Pattern:


Appearance Add new Edit this post Nitesh Synergy
Sol-1:
Basic Singleton Implementation (Eager
Initialization):

• Advantages: Simple, thread-safe without additional


synchronization.
• Disadvantages: Instance is created at class
loading, even if it’s never used.

public class Singleton {


private static final Singleton INSTANCE = new
Singleton(); // Static instance

private Singleton() {
// Private constructor
}

public static Singleton getInstance() {


return INSTANCE; // Global access point
}
}

Sol-2:
Lazy Initialization
• Advantages: Instance is created only when
required.
• Disadvantages: Not thread-safe.

public class Singleton {


private static Singleton instance;

private Singleton() {
// Private constructor
}

public static Singleton getInstance() {


if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

Sol-3:

Thread-Safe Singleton (Synchronized Method)

• advantages: Thread-safe.

5 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance
• DiEdit
Add new
sadthis
vanpost
tages: Performance overhead due to Nitesh Synergy
synchronized method.

public class Singleton {


private static Singleton instance;

private Singleton() {
// Private constructor
}

public static synchronized Singleton


getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

Sol-4:

Thread-Safe Singleton (Double-Checked Locking)

• Advantages: Efficient, avoids unnecessary


synchronization after initialization.
• Disadvantages: Requires understanding of volatile
keyword.

→ For all keywords -[Link]


java

public class Singleton {


private static volatile Singleton instance;

private Singleton() {
// Private constructor
}

public static Singleton getInstance() {


if (instance == null) {
synchronized ([Link]) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

Sol-5:
Reflection Safety:

6 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


public class Singleton {
private static Singleton instance;
private Singleton() {
// Prevent Reflection from creating another
instance
if (instance != null) {
throw new
IllegalStateException("Singleton instance already
created!");
}
}
public static Singleton getInstance() {
if (instance == null) {
synchronized ([Link]) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

Sol-6:

Singleton with Enum (Best Practice):

// Singleton Enum for Logging Utility


public enum Logger {
INSTANCE;
// Method to log messages
public void log(String message) {
[Link]("LOG: " + message);
}
// Method to log errors
public void logError(String errorMessage) {
[Link]("ERROR: " +
errorMessage);
}
}
public class UserService {
// Some user-related logic
public void createUser(String username) {
// Log an informational message
[Link]("User creation started
for: " + username);

try {
// Simulating user creation logic
if (username == null ||
[Link]()) {
throw new
IllegalArgumentException("Username cannot be null

7 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

or empty");
Appearance Add new Edit this post Nitesh Synergy
}
// Simulate user created
[Link]("User created
successfully: " + username);
} catch (Exception e) {
// Log the error using Singleton Logger
[Link]("Error
creating user: " + [Link]());
}
}
}

Sol-7:

Preventing Cloning via the clone() Method:

public class Singleton {


private static Singleton instance;
private Singleton() {
if (instance != null) {
throw new
IllegalStateException("Singleton instance already
created!");
}
}
public static Singleton getInstance() {
if (instance == null) {
synchronized ([Link]) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
@Override
public Object clone() {
throw new
CloneNotSupportedException("Cloning of Singleton
is not allowed!");
}
}

Sol-8:

Preventing Serialization Attack:

public class Singleton implements Serializable {


private static final long serialVersionUID =
1L;
private static Singleton instance;

8 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

private Singleton() {
Appearance Add new Edit this post Nitesh Synergy
if (instance != null) {
throw new
IllegalStateException("Singleton instance already
created!");
}
}
public static Singleton getInstance() {
if (instance == null) {
synchronized ([Link]) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
// Ensure Singleton instance is preserved
during serialization/deserialization
protected Object readResolve() {
return instance;
}
}

Sol-9:

Using a Static Block (Eager Initialization with Reflection


Safety):

public class Singleton {


private static final Singleton instance;
static {
try {
instance = new Singleton();
} catch (Exception e) {
throw new
IllegalStateException("Singleton instance already
created!");
}
}
private Singleton() {
// Prevent Reflection from creating another
instance
if (instance != null) {
throw new
IllegalStateException("Singleton instance already
created!");
}
}
public static Singleton getInstance() {
return instance;
}

9 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

}
Appearance Add new Edit this post Nitesh Synergy

Sol-10:

Use of final Keyword:

public class Singleton {


private static final Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {
// Prevent Reflection from creating another
instance
if (instance != null) {
throw new
IllegalStateException("Singleton instance already
created!");
}
}
public static Singleton getInstance() {
return instance;
}
}

There are many other option to create Singleton class.


→T

Below code for Singleton breaking ways:

//Code to break: 1. Reflection


class BreakWithReflection {
public static void breakWithReflection() {
try {
Singleton instance1 =
[Link]();
Constructor<Singleton> constructor =
[Link]();
[Link](true); //
Bypass private access
Singleton instance2 =
[Link]();
[Link](" From
breakWithReflection");

[Link]([Link]());

[Link]([Link]());
} catch (Exception e) {
[Link]();
}
}
}

10 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


//2. Serialization/Deserialization way break
class BreakWithSerialization {
public static void breakWithSerialization()
throws Exception {
Singleton instance1 =
[Link]();
// Serialize instance
ObjectOutputStream out = new
ObjectOutputStream(new
FileOutputStream("[Link]"));
[Link](instance1);
[Link]();
// Deserialize instance
ObjectInputStream in = new
ObjectInputStream(new
FileInputStream("[Link]"));
Singleton instance2 = (Singleton)
[Link]();
[Link]();
[Link](" From
breakWithSerialization");
[Link]([Link]());
[Link]([Link]());
}
}

// 3. Cloning way break


class BreakWithCloning {
public static void breakWithCloning() throws
CloneNotSupportedException {
Singleton instance1 =
[Link]();
Singleton instance2 = (Singleton)
[Link](); // If clone() is accessible
[Link](" From
breakWithCloning");
[Link]([Link]());
[Link]([Link]());
}
}

// 4. Multithreading (Race Condition)


class BreakWithMultithreading {
public static void breakWithMultithreading() {
Runnable task = () -> {
Singleton instance =
[Link]();

[Link]([Link]());
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
[Link](" From

11 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

BreakWithMultithreading");
Appearance Add new Edit this post Nitesh Synergy
[Link]();
[Link]();
}
}

//5. Garbage Collection


class BreakWithGarbageCollection {
public static void breakWithGarbageCollection()
{
Singleton instance =
[Link]();
WeakReference<Singleton> weakRef = new
WeakReference<>(instance);
instance = null; // Nullify the strong
reference
[Link](); // Force garbage collection
[Link](" From
breakWithGarbageCollection");
Singleton newInstance =
[Link]();
[Link]([Link]() ==
newInstance); // False if GC removed the weak
reference
}
}

//6. Subclassing
class BreakWithSubclassing {
public static void breakWithSubclassing() {
// Singleton subclassInstance = new
Singleton() {}; // Anonymous subclass
//
[Link]([Link]());
}
}

class Singleton{
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}

// // If clone() is accessible, // 3. Cloning


way break
@Override
public Object clone() throws
CloneNotSupportedException {
return [Link]();

12 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

}
Appearance Add new Edit this post Nitesh Synergy

public void showMessage() {


[Link]("Singleton Instance");
}
}

package
[Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class Demo1 {
public static void main(String[] args) throws
Exception {
/* Singleton s1 = [Link]();
[Link]([Link]());
Singleton s2 = [Link]();
[Link]([Link]());
*/
[Link]();

[Link]();
[Link]();

[Link]();

[Link]
ion();

[Link]();
}
//Prevention Strategies:
//Prevent Reflection: Add a check in the
private constructor.
/* private Singleton() {
if (instance != null) {
throw new
IllegalStateException("Instance already
created!");
}
}*/
//Serialization Protection: Implement
readResolve().
/* protected Object readResolve() {
return instance;
}*/
//Prevent Cloning: Override clone() and throw
an exception.
//java

13 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

//Copy code
Appearance Add new Edit this post Nitesh Synergy
@Override
protected Object clone() throws
CloneNotSupportedException {
throw new
CloneNotSupportedException("Cannot clone
singleton");
}
//Thread-Safe Initialization: Use Bill Pugh
Singleton or Double-Checked Locking.
//Final Class: Declare the class as final to
prevent subclassing.

✅ Real-World Use Cases of Singleton Class

🏦 1. Banking System Use Case


Use Case: Centralized Transaction Manager

• In a banking application, all deposit, withdrawal,


and transfer operations must go through a single
TransactionManager to maintain consistency.
• This manager must be a Singleton to ensure that
all operations are logged and validated through
one point—preventing data inconsistencies in
concurrent environments.

🔹 Why Singleton?

• Ensures one version of the transaction flow logic


• Prevents double processing or conflicting
operations

🔗 2. JDBC Connection Pool (Database


Access Layer)
Use Case: DatabaseConnectionManager Singleton

• In any Java app (or backend API), database


operations use JDBC.
• A DatabaseConnectionManager class can be Singleton
so it maintains a single connection pool reused by
all DAOs (Data Access Objects).

🔹 Why Singleton?

• Saves system resources


• Manages connection limits efficiently
• Reduces overhead of repeatedly opening/closing
connections

🎮 3. Gaming Application
Use Case: GameSettings or GameEngine Singleton

14 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance
• InEdit
Add new
a this
game,
post
GameSettings (like resolution, sound Nitesh Synergy
level, difficulty level) are set once and used
across multiple levels/screens.
• Or the GameEngine managing game loop, rendering,
and physics should only be one across the app.

🔹 Why Singleton?

• Consistent behavior across game scenes


• Prevents re-initializing core game logic
• Shares resources like physics engine, AI logic
across levels

🤖 4. AI/ChatGPT-Based App Use Case


Use Case: AIModelManager or APIClientManager

Imagine building an AI-based tool like ChatGPT:

• You integrate OpenAI or a custom LLM into your


system.
• A Singleton class (e.g., AIModelManager) ensures
the prompt formatting, token handling, or rate-
limit logic is handled centrally.
• Or a Singleton APIClient manages the HTTP
connection, headers, and authorization tokens.

🔹 Why Singleton?

• Avoids multiple heavy model initializations


• Centralized control over API call logic
• Manages rate limits, retries, and tokens from one
place
• Reduces latency by reusing configuration and
headers

📌 Summary Table

Domain Singleton Class Example Purpose

Maintain
Banking TransactionManager consistency and
log transactions

Reuse DB
JDBC/ connections,
DatabaseConnectionManager
Backend optimize
resource usage

Global settings
Gaming GameEngine / GameSettings and logic across
game screens

Centralized
AI AIModelManager /
model config and
Tools APIClient
API management

15 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


→ Perfect Singleton:GameEngine Singleton (Central
Control for a Game App)
✅ [Link] — Perfect
Singleton for Game Engine
package [Link];

import [Link];

public final class GameEngineSingleton implements


Serializable, Cloneable {

private static class GameEngineHelper {


private static final GameEngineSingleton INSTANCE =
new GameEngineSingleton();
}

private GameEngineSingleton() {
if ([Link] != null) {
throw new IllegalStateException("Instance already
created!");
}
}

public static GameEngineSingleton getInstance() {


return [Link];
}

@Override
protected Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException("Cloning not
allowed for GameEngineSingleton");
}

protected Object readResolve() {


return getInstance();
}

// Game-related logic
public void startGame() {
[Link]("Game started...");
}

public void stopGame() {


[Link]("Game stopped...");
}

public void updateGameState() {


[Link]("Game state updated.");
}
}

✅ [Link] — Client
Code to Use Singleton
package [Link];

public class GameEngineClient {


public static void main(String[] args) {
GameEngineSingleton engine1 =
[Link]();

16 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

GameEngineSingleton engine2 =
Appearance Add new Edit this post Nitesh Synergy
[Link]();

[Link]();
[Link]();

[Link](engine1 == engine2); // true —


proves Singleton
}
}

Why Singleton is Ideal Here?

Reason Explanation

Avoids multiple heavy


💾 Resource
initializations of rendering or
Management
sound engines.

🔄 Global Game progress, score, and events


State stay consistent across game screens.

🎮 Central Game loop and state transitions are


Control managed centrally.

Protected from cloning, reflection,


✅ Safety
and serialization issues.

→ Next

Factory Pattern

✅ What is Factory Pattern?

The Factory Pattern is a creational design pattern that


provides an interface or method for creating objects without
exposing the creation logic to the client.

Instead, the client uses a method to get instances based on a


type, name, or key.

✅ When to Use Factory Pattern?


• When the class you need to instantiate depends on
input or context.
• When you want to avoid tight coupling between the
code using the objects and the object types.
• When the object creation logic is complex,
repetitive, or conditional.

✅ Why Use It?


• Centralized Object Creation: Keeps creation logic
in one place.
• Encapsulation: Hides complexities of
instantiation.
• Polymorphism: Returns objects of the same

17 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

interface but different implementations.


Appearance Add new Edit this post Nitesh Synergy
• Maintainability: New types can be added with
minimal code changes (Open/Closed Principle).

❌ Why NOT Use It?


• Overkill for Simple Scenarios: If object creation
is trivial, Factory adds unnecessary abstraction.
• Too Many Classes: Each object type might require a
new class, increasing complexity.

🎯 Use Cases
• UI Components (Buttons, Windows, Themes)
• Payment Gateways (CreditCard, PayPal, UPI)
• Notification Systems (Email, SMS, Push)
• Gaming Characters (Player, Enemy, NPCs)
• Vehicle Production (Car, Bike, Truck)

Use Case: Drawing different shapes


Client asks: "Give me a shape: circle, square, or rectangle"

Factory returns appropriate object and client just calls


draw() .

Use Case: Create different in-game characters dynamically


(Player, Enemy, PowerUp, Boss)

→ Common Interface:
public interface GameCharacter {
void action();
}

Implementations:

public class Player implements GameCharacter {


public void action() {
[Link]("Player attacks with sword.");
}
}

public class Enemy implements GameCharacter {


public void action() {
[Link]("Enemy shoots arrows.");
}
}

public class PowerUp implements GameCharacter {


public void action() {
[Link]("PowerUp grants extra life.");
}
}

public class Boss implements GameCharacter {


public void action() {

18 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

[Link]("Boss unleashes special power.");


Appearance Add new Edit this post Nitesh Synergy
}
}

Factory Class :

public class GameCharacterFactory {


public static GameCharacter createCharacter(String type)
{
return switch ([Link]()) {
case "player" -> new Player();
case "enemy" -> new Enemy();
case "powerup" -> new PowerUp();
case "boss" -> new Boss();
default -> throw new
IllegalArgumentException("Unknown character type");
};
}
}

Client Code:

public class GameApp {


public static void main(String[] args) {
GameCharacter player =
[Link]("player");
GameCharacter enemy =
[Link]("enemy");
GameCharacter boss =
[Link]("boss");

[Link]();
[Link]();
[Link]();
}
}

✅Why Factory is
Ideal Here
With Factory
Aspect Without Factory
Pattern

Centralized in
Object Scattered in
one factory
Creation multiple places
class

Just extend
Adding New
Modify client code factory + new
Character
class

Handled
Manually handled
Polymorphism elegantly via
or inconsistent
interface

Low — tightly High — loosely


Flexibility
coupled coupled

19 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post With Factory Nitesh Synergy
Aspect Without Factory
Pattern

Harder due to
Testing and Easy to mock via
direct
Mocking interface
instantiation

Open/Closed Violated when


Fully respected
Principle modifying logic

✅ Factory Pattern is essential when your app needs:

• Flexible and dynamic object creation


• Better maintainability
• Polymorphic behavior via interfaces
• Centralized control over creation logic

Prototype Pattern

Prototype Pattern lets you create objects by cloning an


existing object (the prototype), instead of instantiating a
new one using new .

Use Case
• Games: Creating characters, weapons, or other
entities with shared configurations.
• Document Processing: Cloning complex document
templates.
• GUI Applications: Reproducing UI elements like
buttons and windows.
• Simulations: Copying complex objects like vehicles
or terrain.

Step 1: Common Interface


public interface Prototype extends Cloneable {
Prototype clone();
}

Step 2: Concrete Prototype Classes


public class Circle implements Prototype {
private int radius;

public Circle(int radius) {


[Link] = radius;
}

public void setRadius(int radius) {


[Link] = radius;
}

20 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

@Override
Appearance Add new Edit this post Nitesh Synergy
public Prototype clone() {
return new Circle([Link]);
}

@Override
public String toString() {
return "Circle with radius " + radius;
}
}

public class Rectangle implements Prototype {


private int width;
private int height;

public Rectangle(int width, int height) {


[Link] = width;
[Link] = height;
}

public void setDimensions(int width, int


height) {
[Link] = width;
[Link] = height;
}

@Override
public Prototype clone() {
return new Rectangle([Link],
[Link]);
}

@Override
public String toString() {
return "Rectangle [width=" + width + ",
height=" + height + "]";
}
}

Step 3: Prototype Registry

import [Link];
import [Link];

public class PrototypeRegistry {


private Map<String, Prototype> prototypes =
new HashMap<>();

public void addPrototype(String key, Prototype


prototype) {
[Link](key, prototype);
}

21 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


public Prototype getPrototype(String key) {
Prototype prototype = [Link](key);
return prototype != null ?
[Link]() : null;
}
}

Step 4: Client Code

public class Main {


public static void main(String[] args) {
// Create prototype objects
Circle circlePrototype = new Circle(10);
Rectangle rectanglePrototype = new
Rectangle(20, 30);

// Register prototypes
PrototypeRegistry registry = new
PrototypeRegistry();
[Link]("circle",
circlePrototype);
[Link]("rectangle",
rectanglePrototype);

// Create new objects by cloning


Circle clonedCircle = (Circle)
[Link]("circle");
Rectangle clonedRectangle = (Rectangle)
[Link]("rectangle");

// Modify clones
[Link](15);
[Link](40, 50);

// Print results
[Link](clonedCircle); //
Circle with radius 15
[Link](clonedRectangle); //
Rectangle [width=40, height=50]
}
}

Gaming Code: Cloning Game


Entities
A game has various entities (e.g., players, enemies,
and weapons) with complex initialization logic.
Instead of recreating entities, we clone pre-
configured prototypes.

22 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


Step 1: Common Interface

public interface GameEntity extends Cloneable {


GameEntity clone();
void render();
}

Step 2: Concrete Entity Classes


public class Player implements GameEntity {
private String name;
private int health;
private int attackPower;

public Player(String name, int health, int


attackPower) {
[Link] = name;
[Link] = health;
[Link] = attackPower;
}

public void setAttributes(String name, int


health, int attackPower) {
[Link] = name;
[Link] = health;
[Link] = attackPower;
}

@Override
public GameEntity clone() {
return new Player([Link], [Link],
[Link]);
}

@Override
public void render() {
[Link]("Player: " + name + ",
Health: " + health + ", Attack Power: " +
attackPower);
}
}

public class Enemy implements GameEntity {


private String type;
private int health;

public Enemy(String type, int health) {


[Link] = type;
[Link] = health;
}

public void setAttributes(String type, int


health) {
[Link] = type;

23 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

[Link] = health;
Appearance Add new Edit this post Nitesh Synergy
}

@Override
public GameEntity clone() {
return new Enemy([Link], [Link]);
}

@Override
public void render() {
[Link]("Enemy: " + type + ",
Health: " + health);
}
}

Step 3: Prototype Registry

import [Link];
import [Link];

public class GameEntityRegistry {


private Map<String, GameEntity> prototypes =
new HashMap<>();

public void addPrototype(String key,


GameEntity entity) {
[Link](key, entity);
}

public GameEntity getPrototype(String key) {


return [Link](key).clone();
}
}

Step 4: Client Code


public class GameMain {
public static void main(String[] args) {
// Create prototypes
Player playerPrototype = new
Player("Default Player", 100, 50);
Enemy enemyPrototype = new Enemy("Zombie",
75);

// Register prototypes
GameEntityRegistry registry = new
GameEntityRegistry();
[Link]("player",
playerPrototype);
[Link]("zombie",
enemyPrototype);

// Clone and modify entities


Player player1 = (Player)
[Link]("player");

24 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

[Link]("Player1", 120, 60);


Appearance Add new Edit this post Nitesh Synergy

Enemy zombie1 = (Enemy)


[Link]("zombie");
[Link]("Zombie1", 80);

// Render entities
[Link]();
[Link]();
}
}

Output Example

Player: Player1, Health: 120, Attack Power: 60


Enemy: Zombie1, Health: 80

Builder Pattern

Builder Pattern lets you create a complex object in parts,


using simple steps — and you control how it’s built.

✅ Why is Builder Pattern needed?


1. ✅ When an object has lots of optional fields or
configurations

2. ✅ When object construction is too complex to handle in a


single constructor

3. ✅ To make code clean, readable, and maintainable

4. ✅ To create different variations of the same object


easily

🔍 Real-life Analogy:
Imagine building a burger at a restaurant:
You choose bun, cheese, veggies, sauces, etc.
The Burger Builder prepares it step-by-step.
You get the final burger your way 🍔

Use Case
1. Constructing objects with many optional
parameters, such as HTTP requests.
2. Building vehicles in games, e.g., tanks, cars, and
planes.
3. Assembling complex entities in RPG games, e.g.,
player profiles or NPCs.

Step 1: Product Class

25 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

public class House {


Appearance Add new Edit this post Nitesh Synergy
private String foundation;
private String structure;
private String roof;
public void setFoundation(String foundation) {
[Link] = foundation;
}
public void setStructure(String structure) {
[Link] = structure;
}
public void setRoof(String roof) {
[Link] = roof;
}
@Override
public String toString() {
return "House [Foundation=" + foundation +
", Structure=" + structure + ", Roof=" + roof +
"]";
}
}

Step 2: Builder Interface


public interface HouseBuilder {
void buildFoundation();
void buildStructure();
void buildRoof();
House getHouse();
}

Step 3: Concrete Builders


public class WoodenHouseBuilder implements
HouseBuilder {
private House house = new House();

@Override
public void buildFoundation() {
[Link]("Wooden Foundation");
}

@Override
public void buildStructure() {
[Link]("Wooden Structure");
}

@Override
public void buildRoof() {
[Link]("Wooden Roof");
}

@Override
public House getHouse() {
return house;
}
}

26 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


public class StoneHouseBuilder implements
HouseBuilder {
private House house = new House();

@Override
public void buildFoundation() {
[Link]("Stone Foundation");
}

@Override
public void buildStructure() {
[Link]("Stone Structure");
}

@Override
public void buildRoof() {
[Link]("Stone Roof");
}

@Override
public House getHouse() {
return house;
}
}

Step 4: Director

public class HouseDirector {


private HouseBuilder builder;

public HouseDirector(HouseBuilder builder) {


[Link] = builder;
}

public House constructHouse() {


[Link]();
[Link]();
[Link]();
return [Link]();
}
}

Step 5: Client Code

public class BuilderDemo {


public static void main(String[] args) {
HouseBuilder woodenBuilder = new
WoodenHouseBuilder();
HouseDirector director = new
HouseDirector(woodenBuilder);
House woodenHouse =
[Link]();
[Link](woodenHouse);

27 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


HouseBuilder stoneBuilder = new
StoneHouseBuilder();
director = new
HouseDirector(stoneBuilder);
House stoneHouse =
[Link]();
[Link](stoneHouse);
}
}

Output Example
House [Foundation=Wooden Foundation,
Structure=Wooden Structure, Roof=Wooden Roof]
House [Foundation=Stone Foundation,
Structure=Stone Structure, Roof=Stone Roof]

Abstract Factory Pattern

Factory of factories — gives you a group of related objects


(like a complete theme or product set), not just one.

• Key Idea: Encapsulates the creation of families of


related objects.
• Advantage: Ensures that products in a family are
compatible and grouped logically.
• ✅ Why is Abstract Factory Pattern
needed?
• ✅ When your system needs to create related objects
together (e.g., Button + Checkbox in a UI toolkit).

• ✅ To ensure compatibility among created objects.

• ✅ To support multiple product families easily.

• ✅ It keeps code decoupled from concrete classes.

• 🔍 Real-life Analogy:
• Imagine a Furniture Factory:

• A ModernFurnitureFactory gives you: Modern Chair, Modern


Table

• A VictorianFurnitureFactory gives you: Victorian Chair,


Victorian Table
You get a complete set of compatible products, not just
one.

Use Case
1. Cross-platform UI: Creating compatible widgets
like buttons and checkboxes for Windows, Mac, and
Linux.
2. Gaming: Creating characters, weapons, and armor

28 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

for different factions or races.


Appearance Add new Edit this post Nitesh Synergy
3. Payment Gateways: Creating configurations for
PayPal, Stripe, and UPI systems.

🏦 Scenario:
You want to create banking-related objects: Loan and Account.
Depending on the Bank (e.g., HDFC or SBI), the system should
return the corresponding Account and Loan.

Step 1: Product Interfaces

interface Account {
void accountType();
}

interface Loan {
void loanType();
}

Step 2: Concrete Products – HDFC

class HDFCAccount implements Account {


public void accountType() {
[Link]("HDFC Savings Account");
}
}

class HDFCLoan implements Loan {


public void loanType() {
[Link]("HDFC Home Loan");
}
}

Step 3: Concrete Products – SBI

class SBIAccount implements Account {


public void accountType() {
[Link]("SBI Current Account");
}
}

class SBILoan implements Loan {


public void loanType() {
[Link]("SBI Personal Loan");
}
}

Step 4: Abstract Factory

interface BankFactory {
Account createAccount();
Loan createLoan();
}

Step 5: Concrete Factories

class HDFCBankFactory implements BankFactory {

29 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

public Account createAccount() {


Appearance Add new Edit this post Nitesh Synergy
return new HDFCAccount();
}
public Loan createLoan() {
return new HDFCLoan();
}
}

class SBIBankFactory implements BankFactory {


public Account createAccount() {
return new SBIAccount();
}
public Loan createLoan() {
return new SBILoan();
}
}

Step 6: Factory Creator

class BankFactoryProvider {
public static BankFactory getBankFactory(String bank) {
return switch ([Link]()) {
case "hdfc" -> new HDFCBankFactory();
case "sbi" -> new SBIBankFactory();
default -> throw new
IllegalArgumentException("Unknown bank");
};
}
}

Step 7: Client Code

public class Main {


public static void main(String[] args) {
BankFactory bankFactory =
[Link]("hdfc");

Account account = [Link]();


[Link](); // Output: HDFC Savings
Account

Loan loan = [Link]();


[Link](); // Output: HDFC Home Loan
}
}

🧩 Creational Design Patterns


Comparison Table

Feature / Factory Abstract


Builder Prototype Singleton
Pattern Method Factory

Create Create
Clone Ensure on
objects via related Build complex object
Purpose existing instance
subclass or families of step-by-step
object app
method objects

30 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance FeatuEdit
Add new re this
/ postFactory Abstract Nitesh Synergy
Builder Prototype Singleton
Pattern Method Factory

Cloning
Object Uses method/ Uses factory Step-wise Lazy or e
existing
Creation logic for families construction initializ
object

Flexibility Medium High High Medium Low

Client ❌ No (dir
✅ Knows
Knows ❌ No ❌ No ✅ Yes (via builder) access vi
prototype
Concrete? static me

App-wide
Vary object Vary product Complex object (many Duplicate
When to config/
by input/ family across configs, configured
Use resource
context app immutability) object
manager

GameUIFactory
Clone GameSetti
Key EnemyFactory → MacOS/
GameCharacterBuilder Enemy (volume,
Example → creates Windows
→ Hero with weapons object with level, us
(Game) Orc/Zombie buttons,
new HP ID)
menus

Easy to Runtime Global ac


Main Decouples Code clarity,
switch object object to same
Advantage instantiation immutability
families duplication instance

Many
Class Hidden
interfaces, Shallow vs.
Main explosion Verbose if simple dependenc
can be deep copy
Drawback (many objects threading
abstract- issues
factories) issues
heavy

Furniture
Pizza shop factory
Real-World Meal builder (choose Copying a Governmen
with types (Modern/
Analogy base, sides, drink) filled form system
(Veg/Non-Veg) Victorian
sets)

Complexity ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐ ⭐

Common Java, C#, Java, C++, Java, C#,


Java, C# Java, Kotlin, Python
Languages Python JS Python

📌 Short Summary of Each Pattern


• Factory – Choose one object from many possible
(like selecting a payment method).
• Abstract Factory – Choose a set of related objects
(UI for Windows vs Mac).
• Builder – Construct an object step by step, with
flexibility.
• Prototype – Clone an already existing object (pre-
configured).
• Singleton – Only one instance, used globally (like
configuration manager).

31 of 32 07/11/25, 10:12 pm
Design Pattern [Link]

Appearance Add new Edit this post Nitesh Synergy


Structural Design
Pattern
Adapter Pattern:

 23 min read

 Jun 12, 2025

 By Nitesh Synergy

SHARE

32 of 32 07/11/25, 10:12 pm

You might also like