【设计模式学习】单例模式模拟数据库连接池




作业:使用单例模式模拟数据库连接池。要求客户端代码可以获取连接池的唯一对象,并且可以从池中随机取一个连接对象来连接数据库。



使用单例模式实现数据库连接池对象。




单例模式的优点:



  1. 提供对唯一实例的受控访问;

  2. 节约系统资源,防止出现 Java 版内存泄露;

  3. 允许可变数目的实例(没看懂)。



单例模式的缺点



  1. 没有抽象层,对拓展有很大困难;

  2. 单例类指责过重;

  3. 语言的垃圾回收机制可能导致共享的单例对象状态丢失。



适用场景



  1. 系统只需要一个实例对象;

  2. 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。



我的代码




package test;
import java.util.LinkedList;
class Connection {
private int id;
public Connection(int id) {
this.id = id;
}
public String toString() {
return String.valueOf(id);
}
}
class DataSource {
private int maxCount; // 最大连接数
private int minCount; // 最低连接数
private int nowCreatedCount = 0; // 当前已创建连接数
private LinkedList<Connection> connections = new LinkedList<Connection>();
private static class HolderClass { // 使用 IoDH 方式获取单例
private static final DataSource instance = new DataSource();
}
public static DataSource getInstance() {
return HolderClass.instance;
}
private DataSource() {
// 假设从配置文件中读取到了数据
maxCount = 10;
minCount = 5;
nowCreatedCount = 0;
if (minCount > maxCount) {
throw new ExceptionInInitializerError("数据库连接池初始化异常");
}
for (int i = 0; i < minCount; i++) {
Connection conn = new Connection(i);
connections.addLast(conn);
nowCreatedCount++;
}
System.out.println("数据库连接池初始化完毕, 当前已创建连接个数为:" + nowCreatedCount);
}
public Connection getConn() throws Exception {
synchronized (connections) {
if (this.connections.size() > 0) {
System.out.println("成功获取连接");
return connections.removeLast();
}
if (nowCreatedCount < maxCount) {
Connection conn = new Connection(nowCreatedCount++);
System.out.println("增加连接, 当前已创建连接个数为:" + nowCreatedCount);
System.out.println("成功获取连接");
return conn;
}
}
throw new Exception("connection full!");
}
public void free(Connection conn) {
connections.addLast(conn);
}
}
public class PlayConnectionPool {
public static void main(String[] args) throws Exception {
DataSource ds = DataSource.getInstance();
System.out.println(ds.getConn());
System.out.println(ds.getConn());
System.out.println(ds.getConn());
System.out.println(ds.getConn());
System.out.println(ds.getConn());
System.out.println(ds.getConn());
System.out.println(ds.getConn());
}
}