单例模式
设计模式是一套反复使用、多数人知晓、经过分类编目的代码设计经验的总结。使用设计模式是为了保证代码的可靠性,提高工作效率、让代码更容易被他人理解。
使用单例模式改造数据库连接功能
1.加载配置数据
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///dao?serverTimezone=GMT-8
jdbc.username=root
jdbc.password=ywh
2.获取数据库连接对象
使用Coonnection getConnection()方法获取数据库连接,返回Connection实例。
3.处理查询操作
ResultSet execute(Connection,PreparedStatement,ResultSet,String,Object[])方法,负责根据传入完成的查询操作,返回结果集ResultSet。
4.处理增、删、改操作
使用int execute(Connection,PreparedStatement,String,Object[ ])方法根据传入的参数完成数据的更新(增、删、改)操作,返回影响的行数
5.关闭数据库连接
使用boolean closeResource(Connection,PreparedStatement,ResultSet)方法,负责根据传入的参数进行相应资源的关闭操作,返回boolean值。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
// 私有静态变量,持有唯一的数据库连接实例
private static DatabaseConnection instance;
// 私有成员变量,保存数据库连接
private Connection connection;
// 私有构造函数,防止外部直接创建实例
private DatabaseConnection() {
// 初始化数据库连接,这里仅为示例,实际使用时可能需要更复杂的逻辑
// 注意:这里直接创建连接可能不是最佳实践,特别是当需要频繁打开和关闭连接时
// 更好的做法是使用连接池
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/yourDatabase";
String user = "yourUsername";
String password = "yourPassword";
connection = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
// 提供一个公共的静态方法用于获取数据库连接实例
public static DatabaseConnection getInstance() {
// 如果实例不存在,则创建实例
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
// 提供一个方法来获取数据库连接
public Connection getConnection() {
return connection;
}
// 可以在这里添加关闭连接的方法,但通常不建议在单例模式中关闭连接
// 因为这可能会导致后续尝试使用连接时出现问题
// public void closeConnection() {
// if (connection != null) {
// try {
// connection.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
// }
// }
// 注意:在应用程序关闭时,你应该关闭数据库连接
// 这通常通过应用程序的关闭钩子或容器管理来完成
}
// 使用示例
public class Main {
public static void main(String[] args) {
DatabaseConnection db = DatabaseConnection.getInstance();
Connection conn = db.getConnection();
// 使用conn进行数据库操作...
// 注意:在实际应用中,你需要在适当的时候关闭连接
// 但在这个单例模式中,你可能不会在每次使用后都关闭连接
// 相反,你可能会在应用程序关闭时关闭连接
}
}
一个类只有一个实例
当一个类被设计为只有一个实例时,这种设计模式被称为单例模式(Singleton Pattern)。单例模式确保了一个类仅有一个实例,并提供了一个全局访问点来获取这个实例。
单例模式的主要目的是在系统中严格控制某些类的实例数量,确保只有一个全局唯一的实例,从而避免资源的重复创建和消耗,或者实现全局访问某些资源的特性。
单例模式有多种实现方式,但最常见和推荐的包括懒汉式(线程安全)、饿汉式、双重检查锁定(Double-Checked Locking)和静态内部类方式。
public class Singleton {
// 私有构造函数,防止外部实例化
private Singleton() {}
// 私有静态内部类,包含唯一的实例
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 提供一个公共的静态方法获取实例
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
// 类的其他方法...
}
自行创建实例对象
当我们谈论单例模式时,目的是确保类在整个应用程序的生命周期中只有一个实例,并且这个实例是由类本身控制创建的,而不是由类的外部代码(即客户端代码)自行创建的。然而,如果你想要了解如何在不遵循单例模式的情况下自行创建类的实例对象,这实际上是面向对象编程(OOP)的基础。
public class MyClass {
// 类的成员变量
private int id;
private String name;
// 类的构造函数
public MyClass(int id, String name) {
this.id = id;
this.name = name;
}
// 类的其他方法...
public void display() {
System.out.println("ID: " + id + ", Name: " + name);
}
// main 方法,用于演示如何创建 MyClass 的实例
public static void main(String[] args) {
// 自行创建 MyClass 的实例
MyClass myObject1 = new MyClass(1, "Object 1");
MyClass myObject2 = new MyClass(2, "Object 2");
// 调用实例的方法
myObject1.display(); // 输出: ID: 1, Name: Object 1
myObject2.display(); // 输出: ID: 2, Name: Object 2
}
}
public class Singleton {
// 私有静态变量,持有类的唯一实例
private static Singleton instance;
// 私有构造函数,防止外部实例化
private Singleton() {}
// 公共静态方法,用于获取类的唯一实例
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 类的其他方法...
}
// 注意:上面的代码在多线程环境下是线程安全的,但由于每次调用 getInstance() 时都进行同步,所以性能可能不是最优的。
// 在实际应用中,你可能会考虑使用双重检查锁定或静态内部类等方式来提高性能。
懒汉模式和饿汉模式
懒汉模式
定义:懒汉模式(Lazy Initialization)指的是在第一次访问时才创建类的唯一实例。这种实现方式在实例创建开销较大或者实例使用不频繁时,可以减少不必要的资源开销。
特点:
- 延迟加载:实例在第一次被使用时创建,实现了懒加载。
- 线程安全问题:在多线程环境下,如果不加同步控制,懒汉模式可能会导致多个实例被创建,从而违背单例模式的初衷。因此,通常需要使用同步锁(如
synchronized
)来确保线程安全。 - 性能考虑:虽然加锁可以确保线程安全,但每次访问
getInstance
方法时都进行加锁操作会影响性能。为了优化性能,可以采用双重检查锁定(Double-Check Locking)等机制来减少锁的竞争。
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
// 可以进一步优化为双重检查锁定
/*
public static SingletonLazy getInstance() {
if (instance == null) {
synchronized (SingletonLazy.class) {
if (instance == null) {
instance = new SingletonLazy();
}
}
}
return instance;
}
*/
}
二、饿汉模式
定义:饿汉模式(Eager Initialization)指的是在类加载时就创建类的唯一实例。这种实现方式能保证线程安全,因为类加载时的操作是线程安全的。
特点:
- 立即加载:实例在类加载时就已经被创建,实现了立即加载。
- 线程安全:由于实例在类加载时就已经存在,因此不存在多线程同时创建多个实例的问题,天然线程安全。
- 资源占用:无论是否需要使用实例,它都会在类加载时被创建并占用资源,可能导致资源浪费。特别是当类的实例化开销较大或实例化过程复杂时,这种资源占用可能更为明显。
public class SingletonEager {
private static final SingletonEager instance = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return instance;
}
}