文章目录
- 引言
- 对象池模式简介
- 定义与用途
- 实现方式
- 使用场景
- 优势与劣势
- 对象池模式在Spring中的应用
- JDBC对象池示例
- 代码地址
- 小结
引言
对象池模式在资源管理和性能优化方面发挥着重要作用。这种模式通过重复使用已经初始化的对象,而不是频繁创建和销毁,减少了系统的开销。这对于处理如数据库连接、线程和图形对象等资源密集型和性能敏感的系统尤为重要。该模式是属于23种设计模式之外的补充模式。
对象池模式简介
定义与用途
对象池模式是一种创建型设计模式,用于管理和重用对象集合。当一个客户端请求一个新对象时,该模式先检查是否有现有的对象可用,而不是创建一个新对象。如果有可用的对象,它将被重用,否则,创建一个新对象并添加到池中。
实现方式
对象池模式通常涉及以下几个关键组件:
- 对象池类:负责创建和管理对象池。
- 池化对象:池中管理的对象。
- 客户端:请求从池中获取对象的用户。
- 接口/抽象类:定义对象的创建、重用和释放的规范。
工厂方法模式可以用来封装对象的创建逻辑。然而,它在创建之后不管理这些对象,而对象池模式则跟踪它创建的对象。
对象池通常实现为单例。
使用场景
- 资源重用:当系统中对象的创建和销毁开销显著时。
- 性能要求:在性能敏感的应用中,减少创建和销毁对象的次数。
- 资源限制:在资源受限的情况下,如数据库连接或线程池。
优势与劣势
- 优势
提高性能:通过重用现有对象减少创建和销毁对象的开销。
资源管理:有效管理稀缺资源,如数据库连接。 - 劣势
管理复杂性:维护对象池增加了系统的复杂性。
潜在的资源浪费:如果池中对象很少被重用,可能会导致资源浪费。
对象池模式在Spring中的应用
在Spring框架中,并没有直接实现对象池模式,但它提供了相关的支持,使得我们可以方便地实现该模式。例如,Spring的Bean生命周期管理和依赖注入特性可以用于实现自定义的对象池。此外,Spring也提供了与一些常见对象池(如数据库连接池)的集成。
JDBC对象池示例
对象池模式类似于办公室仓库。当新员工被雇佣时,办公室经理需要为他准备工作空间。她会检查办公室仓库是否有备用设备。如果有,她就使用它。如果没有,她就会从亚马逊订购新设备。如果员工被解雇,他的设备会被移动到仓库,以备新工作场所需要时使用。
第1步
创建一个 ObjectPool 类,用于创建对象的数量。
public abstract class ObjectPool<T> {
private long expirationTime;
private ConcurrentHashMap<T, Long> locked, unlocked;
public ObjectPool() {
expirationTime = 30000; // 30 秒
locked = new ConcurrentHashMap<T, Long>();
unlocked = new ConcurrentHashMap<T, Long>();
}
protected abstract T create();
public abstract boolean validate(T o);
public abstract void expire(T o);
public synchronized T checkOut() {
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) {
// 对象已过期
unlocked.remove(t);
expire(t);
t = null;
} else {
if (validate(t)) {
unlocked.remove(t);
locked.put(t, now);
return t;
} else {
// 对象验证失败
unlocked.remove(t);
expire(t);
t = null;
}
}
}
}
// 无可用对象,创建一个新的
t = create();
locked.put(t, now);
return t;
}
public synchronized void checkIn(T t) {
locked.remove(t);
unlocked.put(t, System.currentTimeMillis());
}
}
第2步
创建一个实现类,用于获取jdbc连接。
public class JDBCConnectionPool extends ObjectPool<Connection>{
private String dsn, usr, pwd;
public JDBCConnectionPool(String driver, String dsn, String usr, String pwd) {
super();
try {
Class.forName(driver).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
this.dsn = dsn;
this.usr = usr;
this.pwd = pwd;
}
@Override
protected Connection create() {
try {
return DriverManager.getConnection(dsn, usr, pwd);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
@Override
public void expire(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;
}
}
}
第三步
测试类允许应用程序借用和归还数据库连接:
public class Main {
public static void main(String args[]) {
// 做一些事情...
// 创建 ConnectionPool:
JDBCConnectionPool pool = new JDBCConnectionPool(
"org.hsqldb.jdbcDriver", "jdbc:hsqldb://localhost/mydb",
"sa", "secret");
// 获取一个连接:
Connection con = pool.checkOut();
// 使用连接
// 归还连接:
pool.checkIn(con);
}
}
这个示例展示了如何使用对象池模式管理和重用数据库连接,以优化资源使用和提高性能。
代码地址
23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern
小结
至此,创建型的6种设计模式的总结完成,感兴趣的同学可以看看之前的博客。