23种设计模式之单例模式singleton
1、创建单例模式的原因
节省系统资源、保持数据的一致性。
例子:windows中只能打开一个任务管理器、线程池、数据库连接池、网站计数器等,都被设计成单例模式。
2、单例模式的特点
(1)只有一个实例对象;
(2)由单例类自行创建;
(3)对外提供一个访问该单例的全局访问点。(常用static方法)
3、如何构建单例模式
(1)懒汉式
package cn.function.designmodel; public class SingletonTest { // 静态变量,原子操作 private static volatile SingletonTest singletonTest = null; // 用于外部测试是否是单例 public String name = "我是单例1"; // 通过构造私有的构造方法,防止被外部实例化 private SingletonTest() { }; // 对外提供一个实例化的方法,生成单例 public static SingletonTest getInstance() { if (singletonTest == null) { singletonTest = new SingletonTest(); } return singletonTest; } }
(2)饿汉式
一旦加载类,就创建一个单例
package cn.function.designmodel; /** * 饿汉式 * * @author ycXie * */ public class Singleton2 { // 定义一个常量,引用自身实例 private static final Singleton2 SINGLETON2 = new Singleton2(); public String name = "单例"; // 将构造函数定义为私有类型,防止外部实例化 private Singleton2() { }; // 通过构建一个public的全局访问点,得到该单例 public static Singleton2 getInstance() { return SINGLETON2; } }
测试:
package cn.function.designmodel; public class MainTest { public static void main(String[] args) { SingletonTest singletonTest = SingletonTest.getInstance(); SingletonTest singletonTest2 = SingletonTest.getInstance(); singletonTest.name = "单例1"; singletonTest2.name = "单例2"; System.out.println(singletonTest.name); System.out.println(singletonTest2.name); Singleton2 singleton2 = Singleton2.getInstance(); Singleton2 singleton22 = Singleton2.getInstance(); singleton2.name = "单例3"; singleton22.name = "单例4"; System.out.println(singleton2.name); System.out.println(singleton22.name); } }
结果:
单例2
单例2
单例4
单例4
确实为单例。
4、单例模式的应用实例
数据库连接:
1、DBhelper
package cn.function.designmodel.singleton; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; /** * 单例模式的数据库连接 * * @author ycXie * */ public class DBhelperSingleton { private static volatile DBhelperSingleton dBhelperSingleton = null; public String url; public String name; public Connection conn; public PreparedStatement pst; private DBhelperSingleton(String sql, String url, String name, String username, String password) throws ClassNotFoundException, SQLException { this.url = url; this.name = name; Class.forName(name); conn = DriverManager.getConnection(url, username, password); pst = conn.prepareStatement(sql); }; public static DBhelperSingleton getInstance(String sql, String url, String name, String username, String password) throws ClassNotFoundException, SQLException { if (dBhelperSingleton == null) { dBhelperSingleton = new DBhelperSingleton(sql, url, name, username, password); } return dBhelperSingleton; } public void close() { try { if (conn != null) { conn.close(); } if (pst != null) { pst.close(); } } catch (Exception e) { // TODO: handle exception } } }
2、调用
package cn.function.designmodel.singleton; import java.sql.ResultSet; import java.sql.SQLException; import cn.rigid.hoistmnteg.model.User; public class MainTest { public static void main(String[] args) { SingletonTest singletonTest = SingletonTest.getInstance(); SingletonTest singletonTest2 = SingletonTest.getInstance(); singletonTest.name = "单例1"; singletonTest2.name = "单例2"; System.out.println(singletonTest.name); System.out.println(singletonTest2.name); Singleton2 singleton2 = Singleton2.getInstance(); Singleton2 singleton22 = Singleton2.getInstance(); singleton2.name = "单例3"; singleton22.name = "单例4"; System.out.println(singleton2.name); System.out.println(singleton22.name); String sql = "select * from user"; String url = "jdbc:mysql://localhost:3306/hoistmnt"; String name = "com.mysql.jdbc.Driver"; String username = "root"; String password = "root"; ResultSet rst; User user = new User(); try { DBhelperSingleton dBhelperSingleton = DBhelperSingleton.getInstance(sql, url, name, username, password); DBhelperSingleton dBhelperSingleton2 = DBhelperSingleton.getInstance(sql, "我要改了", name, username, password); rst = dBhelperSingleton.pst.executeQuery(); // 可以发现url没有改变,说明是单例模式 System.out.println(dBhelperSingleton.url); System.out.println(dBhelperSingleton2.url); while (rst.next()) { user.setName(rst.getString("username")); user.setScore(rst.getInt("id")); System.out.println(user); } rst.close(); dBhelperSingleton.close(); } catch (ClassNotFoundException | SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
结果:
单例2 单例2 单例4 单例4 Tue Oct 29 14:34:10 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
jdbc:mysql://localhost:3306/hoistmnt jdbc:mysql://localhost:3306/hoistmnt User [uid=null, name=zhangsan, email=null, phone=null, status=null, timeSend=null, score=1] User [uid=null, name=lisi, email=null, phone=null, status=null, timeSend=null, score=2] User [uid=null, name=wangwu, email=null, phone=null, status=null, timeSend=null, score=8]
警告及原因:原文链接:https://blog.csdn.net/u010429286/article/details/77750177
在JDBC连接Mysql数据库的过程中出现了如下的警告信息:
WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
是Mysql数据库的SSL连接问题,提示警告不建议使用没有带服务器身份验证的SSL连接,是在MYSQL5.5.45+, 5.6.26+ and 5.7.6+版本中才有的这个问题。解决办法在警告中已经说明了:
1.在数据库连接的url中添加useSSL=false;2.url中添加useSSL=true,并且提供服务器的验证证书。如果只是做一个测试的话,没必要搞证书那么麻烦啦,在连接后添加一个useSSL=false即可,例如:
jdbc:mysql://localhost:3306/test?useSSL=false
在使用Java进行JDBC连接的时候,可以在Properties对象中设置useSSL的值为false,但是和写在链接中是一样的。比如
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "milos23);
properties.setProperty("useSSL", "false");
properties.setProperty("autoReconnect", "true");
try (Connection conn = DriverManager.getConnection(connectionUrl, properties)) {
...
} catch (SQLException e) {
..