Object Pool Design Pattern (original) (raw)

Last Updated : 13 May, 2026

The Object Pool Design Pattern is a creational pattern that manages a set of reusable objects to reduce the cost of repeatedly creating and destroying them. Instead of instantiating new objects, clients borrow objects from a pool and return them after use. This improves performance and resource utilization, especially when object creation is expensive.

**Example: In a web application, every user request often needs to interact with a database (e.g., fetching user data, saving orders, etc.). However, creating a new database connection for every request is expensive.

419253541

In the Diagram

Real-World Applications

The Object Pool Pattern is widely used in software systems to efficiently manage and reuse costly resources, improving performance and scalability.

Components

The Object Pool Pattern consists of key elements that manage the creation, reuse, and lifecycle of pooled objects efficiently.

object_pool_design_pattern

UML Diagram

The main components of object pool design pattern:

Uses

The Object Pool Pattern is used in scenarios where object creation is costly and efficient reuse of resources is required.

Object Pool Life Cycle

The lifecycle of objects in an object pool involves the following stages:

Implementation Example

**Problem Statement:

Take the example of the database connections. It's obviously that opening too many connections might affect the performance for several reasons:

Here the object pool manages the connections and provide a way to reuse and share them. It can also limit the maximum number of objects that can be created.

1. Reusable Pool(PooledObject)

Java `

import java.sql.Connection; import java.sql.SQLException;

// This class represents the objects that are expensive to create or have limited availability public class PooledObject { private Connection connection;

public PooledObject(Connection connection) {
    this.connection = connection;
}

public Connection getConnection() {
    return connection;
}

public void close() {
    try {
        connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

public boolean isClosed() {
    try {
        return connection.isClosed();
    } catch (SQLException e) {
        e.printStackTrace();
        return true;
    }
}

}

`

2. Object Pool

Java `

import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; import java.util.Hashtable;

// ObjectPool class maintains a list of available objects and a collection of objects that have already been requested from the pool public abstract class ObjectPool { private long deadTime; private Hashtable<T, Long> lock, unlock;

public ObjectPool() {
    deadTime = 50000; // 50 seconds
    lock = new Hashtable<>();
    unlock = new Hashtable<>();
}

abstract T create();

abstract boolean validate(T o);

abstract void dead(T o);

public synchronized T takeOut() {
    long now = System.currentTimeMillis();
    T t;
    if (unlock.size() > 0) {
        Enumeration<T> e = unlock.keys();
        while (e.hasMoreElements()) {
            t = e.nextElement();
            if ((now - unlock.get(t)) > deadTime) {
                unlock.remove(t);
                dead(t);
                t = null;
            } else {
                if (validate(t)) {
                    unlock.remove(t);
                    lock.put(t, now);
                    return t;
                } else {
                    unlock.remove(t);
                    dead(t);
                    t = null;
                }
            }
        }
    }
    t = create();
    lock.put(t, now);
    return t;
}

public synchronized void takeIn(T t) {
    lock.remove(t);
    unlock.put(t, System.currentTimeMillis());
}

}

`

3. Client

Java `

import java.sql.Connection;

// Client class that uses an object of the PooledObject type public class Client { public static void main(String[] args) { // Create the ConnectionPool: JDBCConnectionPool pool = new JDBCConnectionPool( "org.hsqldb.jdbcDriver", "jdbc:hsqldb: //localhost/mydb", "sa", "password");

    // Get a connection:
    Connection con = pool.takeOut();
    // Return the connection:
    pool.takeIn(con);
}

}

`

Complete code for the above example

The complete code of the above example is:

Java `

import java.util.Enumeration; import java.util.Hashtable;

abstract class ObjectPool { private long deadTime; private Hashtable<T, Long> locked, unlocked;

public ObjectPool()
{
    deadTime = 50000; // 50 seconds
    locked = new Hashtable<>();
    unlocked = new Hashtable<>();
}

protected abstract T create();
protected abstract boolean validate(T o);
protected abstract void expire(T o);

public synchronized T takeOut()
{
    long now = System.currentTimeMillis();
    T t;

    if (!unlocked.isEmpty()) {
        Enumeration<T> e = unlocked.keys();
        while (e.hasMoreElements()) {
            t = e.nextElement();
            if ((now - unlocked.get(t)) > deadTime) {
                unlocked.remove(t);
                expire(t);
            }
            else {
                if (validate(t)) {
                    unlocked.remove(t);
                    locked.put(t, now);
                    return t;
                }
                else {
                    unlocked.remove(t);
                    expire(t);
                }
            }
        }
    }

    t = create();
    locked.put(t, now);
    return t;
}

public synchronized void takeIn(T t)
{
    locked.remove(t);
    unlocked.put(t, System.currentTimeMillis());
}

}

class ConnectionResource { private static int counter = 0; private int id;

public ConnectionResource()
{
    id = ++counter;
    System.out.println("Creating Resource #" + id);
}

public void use()
{
    System.out.println("Using Resource #" + id);
}

public void close()
{
    System.out.println("Closing Resource #" + id);
}

}

class ConnectionPool extends ObjectPool {

@Override protected ConnectionResource create()
{
    return new ConnectionResource();
}

@Override
protected boolean validate(ConnectionResource o)
{
    return o != null;
}

@Override protected void expire(ConnectionResource o)
{
    o.close();
}

}

public class Main { public static void main(String[] args) {

    ConnectionPool pool = new ConnectionPool();

    ConnectionResource r1 = pool.takeOut();
    r1.use();

    pool.takeIn(r1);

    ConnectionResource r2 = pool.takeOut();
    r2.use();

    pool.takeIn(r2);
}

}

`

Output

Creating Resource #1 Using Resource #1 Using Resource #1

Advantages

The Object Pool pattern improves performance and efficient resource management.

Disadvantages

Although efficient, the Object Pool pattern can introduce complexity and risks.