Object Pool Design Pattern

Object Pool Design Pattern là mẫu thiết kế giúp chương trình chúng ta quản lý tốt các objects và được tái sử dụng khi cần thiết. Các lợi ích mà Object Pool mang lại:

* Tái sử dụng các object đã khởi tạo sẵn, giảm thiểu được thời gian khởi tạo object. Cực kỳ hiệu quả đối với các object phải mất nhiều thời gian để khởi tạo.

* Kiểm soát số lượng object được tạo ra, tránh việc chương trình tạo các object một các không kiểm soát.


Tạo một abstract class ObjectPool.java

package vn.fstack.designpattern.objectpool;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map.Entry;

public abstract class ObjectPool<T> {

    private int MAX_POOL = 2; // max number of the object in the pool
    private long expirationTime;
    private Hashtable<T, Long> locked, unlocked;

    public ObjectPool() {
        expirationTime = 30000; // 30 seconds
        locked = new Hashtable<T, Long>();
        unlocked = new Hashtable<T, Long>();
    }

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

    public synchronized T getObject() {
        long now = System.currentTimeMillis();
        T t;
        if (unlocked.size() > 0) {
            Enumeration<T> e = unlocked.keys();
            while (e.hasMoreElements()) {
                t = e.nextElement();
                if ((now - unlocked.get(t)) > expirationTime) {
                    System.out.println("object has expired");
                    unlocked.remove(t);
                    remove(t);
                    t = null;
                } else {
                    if (validate(t)) {
                        unlocked.remove(t);
                        locked.put(t, now);
                        System.out.println("object reuse");
                        return (t);
                    } else {
                        System.out.println("object failed validation");
                        unlocked.remove(t);
                        remove(t);
                        t = null;
                    }
                }
            }
        }
        
        if (locked.size() + unlocked.size() >= MAX_POOL) {
            System.out.println("the created object has exceeded the limit");
            t = null;
        } else {
            System.out.println("create a new one");
            t = create();
            locked.put(t, now);
        }
        
        return (t);
    }

    public synchronized void release(T t) {
        locked.remove(t);
        unlocked.put(t, System.currentTimeMillis());
    }
    
    public synchronized void removeAll() {
        for (Entry<T, Long> entry : locked.entrySet()) {
            remove(entry.getKey());
        }
        for (Entry<T, Long> entry : unlocked.entrySet()) {
            remove(entry.getKey());
        }
    }
}

Các bạn lưu ý 3 phương thức dưới đây sẽ được implement bởi subclass:

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

Bây giờ chúng ta sẽ thử sử dụng mẫu ObjectPool vừa implement ở trên cho việc quản lý các kết nối đến MySQL Server. Chúng ta tạo một class JDBCConnectionPool.java và class Main.java như bên dưới:

package vn.fstack.designpattern.objectpool;

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

public class JDBCConnectionPool extends ObjectPool<Connection> {

    private String url;
    private String username;
    private String password;

    public JDBCConnectionPool(String driver, String url, String username, String password) {
        super();
        try {
            Class.forName(driver).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.url = url;
        this.username = username;
        this.password = password;
    }

    @Override
    protected Connection create() {
        try {
            return (DriverManager.getConnection(url, username, password));
        } catch (SQLException e) {
            e.printStackTrace();
            return (null);
        }
    }

    @Override
    public void remove(Connection o) {
        try {
            ((Connection) o).close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean validate(Connection o) {
        try {
            return (!((Connection) o).isClosed());
        } catch (SQLException e) {
            e.printStackTrace();
            return (false);
        }
    }
}
package vn.fstack.designpattern.objectpool;

import java.sql.Connection;

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

        JDBCConnectionPool pool = new JDBCConnectionPool(
                "com.mysql.cj.jdbc.Driver", 
                "jdbc:mysql://localhost:3306/mysql?useUnicode=true&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC",
                "root", "");

        Connection connect1 = pool.getObject(); // create a new one
        Connection connect2 = pool.getObject(); // create a new one
        Connection connect3 = pool.getObject(); // the created object has exceeded the limit
        pool.release(connect1);
        pool.release(connect2);
        Connection connect4 = pool.getObject(); // object reuse
        Connection connect5 = pool.getObject(); // object reuse
        pool.removeAll();
    }
}

Kết quả sau khi chạy Main.java:

create a new one
create a new one
the created object has exceeded the limit
object reuse
object reuse

Source đầy đủ của ví dụ trong bài này có thể download trên Github qua link bên dưới:

https://github.com/thitranthanh/fstack-blog/tree/master/fstack/fstack-design-pattern