享元模式
本篇文章是通过看视频学习总结的内容, 如有错误的地方请谅解,并联系博主及时修改,谢谢您的阅读.
何为享元模式?
享元模式借名之意就是指,通过设计模式来对数据的共享
适用场景:
数据库连接池、线程池、包装数据类型的 cache,String字符串常量池等,都属于享元模式的使用
享元模式的优点:
- 享元模式起到了对象的复用,减少内存中对象的数量,省去了创建对象消耗的时间,节约内存,提高性能
享元模式的缺点:
- 享元模式存在一定的隐秘性,如果在不了解享元模式的情况下你根本不知道
Integer.valueOf(127) == Integer.valueOf(127) -> true ;
Integer.valueOf(128) == Integer.valueOf(128) -> false;
- 一般情况下,享元模式都是和工厂模式结合使用,例如数据库连接池只能有一个,增加了程序复杂度。
举个例子(连接池):
- 数据库连接池
/**
* <p>
* 享元模式:
* 对象的重复利用,降低重复多次创建可复用的对像的成本
* </p>
*
* @author Zyred
* @date 2020/9/7 21:58
**/
public class ConnectionPool {
private Vector<Connection> pool;
private int initializePoolSize = 127;
private String userName = "root";
private String password = "root";
private String url = "jdbc:mysql://localhost:3306/test";
private String driverClassName ="com.mysql.jdbc.Driver";
public ConnectionPool() {
try {
pool = new Vector<Connection>();
Class.forName(this.driverClassName);
for (int i = 0; i < initializePoolSize; i++) {
Connection conn = DriverManager.getConnection(this.url, this.userName, this.password);
this.pool.add(conn);
}
}catch (Exception ex){
ex.printStackTrace();
}
}
public synchronized Connection getConnection(){
Connection connection = this.pool.get(0);
this.pool.remove(connection);
return connection;
}
public synchronized void release(Connection conn){
this.pool.add(conn);
}
}
- 连接池客户端
/**
* <p>
* 连接池客户端
* </p>
*
* @author zyred
* @createTime 2020/9/8 17:07
**/
public class ConnectionPoolClient {
public static void main(String[] args) {
ConnectionPool pool = new ConnectionPool();
// 得到连接
Connection connection = pool.getConnection();
// TODO
// 关闭
pool.release(connection);
}
}
举个例子 (String 类)
public class StringFlyweight {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "he" + "llo";
String s3 = "he";
String s4 = "llo";
String s5 = s3 + s4;
// true, JDK只对常量的加法做了优化处理,但是没有对定义常量的变量进行处理
System.out.println(s1 == s2);
// false, 这里 s5 是由s3变量加上s4变量得到的,所以,s5不等于 s1
System.out.println(s1 == s5);
}
}
举个例子(Integer 类)
public class IntegerValueOfFlyweight {
/**
* 以下是Integer.valueOf的源码
* public static Integer valueOf(int i) {
* IntegerCache.low = -128;
* IntegerCache.high = 127
* if (i >= IntegerCache.low && i <= IntegerCache.high)
* return IntegerCache.cache[i + (-IntegerCache.low)];
* return new Integer(i);
* }
* @param args
*/
public static void main(String[] args) {
Integer i1 = 127;
Integer i2 = Integer.valueOf(127);
Integer i3 = 128;
Integer i4 = Integer.valueOf(128);
// true
System.out.println(i1 == i2);
// false
System.out.println(i3 == i4);
}
}
总结:
- 在不了解享元模式的情况下,会出现很多的疑惑,例如Integer,Long … 面试一问一个懵
- 使用享元模式,能给系统带来很高性能的提升,如果说到现在我们连接数据库还是用的手动开关 JDBC的方式,那么我们的系统肯定达不到高性能的水平。所以,在某些特定的场景下,如果对象创建销毁特别的消耗性能,那么直接采用享元模式来对齐缓存对象,要使用的时候就直接能获取到。