欢迎关注微信公众号:FSA全栈行动 👋
一、享元模式介绍
享元模式(Flyweight Pattern)属于结构型模式,主要用于减少创建对象的数量,以减少内存占用和提高性能,它提供了减少对象数量从而改善应用所需的对象结构的方式;享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
-
状态
- 内部状态:不会随环境的改变而所有不同,是可以共享的
- 外部状态:它随环境的改变而改变的,是不可以共享的,因此外部状态是由客户端来保持(因为环境的变化一般是由客户端引起)
-
核心组成
- 抽象享元角色:为具体享元角色规定了必须实现的方法,而外部状态就是以参数的形式通过些方法传入
- 具体享元角色:实现抽象角色规定的方法,如果存在内部状态,就负责为内部状态提供存储空间
- 享元工厂角色:负责创建和管理享元角色。(要想达到共享的目的,这个角色很关键)
- 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外部状态
-
应用场景
- Java 中的 String,如果字符串常量池里有则返回,如果没有则创建一个字符串保存在字符串常量池里
- 数据库连接池、线程池等
- 如果系统有大量相似的对象,或者需要用缓冲池的时候可以使用享元模式,也就是大家常说的池化技术
- 如果发现某个对象生成了大量细粒度的实例,并且这些实例除了几个参数外基本是相同的,如果把那些共享参数移到类外面,在方法调用时将他们传递进来,就可以通过共享对象,减少实例的个数
-
优点
- 大大减少了对象的创建,降低了程序内存的占用,提高效率
-
缺点
注意划分内部状态和外部状态,否则可能会引起线程安全问题,必须有一个工厂类加以控制
二、享元模式代码实现
创建 抽象享元角色,规定具体享元角色必须实现的方法:
public abstract class SqlConnection {
protected boolean isConnected;
public abstract void connect();
public abstract void disconnect();
public abstract void create(String sql);
public abstract void delete(String sql);
public abstract void update(String sql);
public abstract String select(String sql);
}
说明:其中成员属性 isConnected 是内部状态,方法参数 sql 是外部状态
创建 具体享元角色:
public class MySqlConnection extends SqlConnection {
@Override
public void connect() {
if (isConnected)
return;
try {
System.out.println("准备连接 mysql数据库...");
Thread.sleep(1000);
System.out.println("成功连接 mysql数据库");
isConnected = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void disconnect() {
System.out.println("已断开 mysql数据库连接");
isConnected = false;
}
@Override
public void create(String sql) {
System.out.println("使用mysql创建数据");
}
@Override
public void delete(String sql) {
System.out.println("使用mysql删除数据");
}
@Override
public void update(String sql) {
System.out.println("使用mysql更新数据");
}
@Override
public String select(String sql) {
System.out.println("使用mysql查询数据");
return null;
}
}
public class OracleConnection extends SqlConnection {
@Override
public void connect() {
if (isConnected)
return;
try {
System.out.println("准备连接 Oracle数据库...");
Thread.sleep(500);
System.out.println("成功连接 Oracle数据库");
isConnected = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void disconnect() {
System.out.println("已断开 Oracle数据库连接");
isConnected = false;
}
@Override
public void create(String sql) {
System.out.println("使用oracle创建数据");
}
@Override
public void delete(String sql) {
System.out.println("使用oracle删除数据");
}
@Override
public void update(String sql) {
System.out.println("使用oracle更新数据");
}
@Override
public String select(String sql) {
System.out.println("使用oracle查询数据");
return null;
}
}
创建 享元工厂角色:
注意:这个工厂类是享元模式的核心,由它管理所有享元对象
public class SqlConnectionFactory {
private static Map<String, SqlConnection> connectionCache = new HashMap<>();
private SqlConnectionFactory() {
}
public static SqlConnection getConnection(String type) {
if (connectionCache.containsKey(type)) {
return connectionCache.get(type);
} else {
SqlConnection sqlConnection = null;
switch (type) {
case "mysql":
sqlConnection = new MySqlConnection();
break;
case "oracle":
sqlConnection = new OracleConnection();
break;
default:
break;
}
if (sqlConnection != null) {
connectionCache.put(type, sqlConnection);
}
return sqlConnection;
}
}
}
如果文章对您有所帮助, 请不吝点击关注一下我的微信公众号:FSA全栈行动, 这将是对我最大的激励. 公众号不仅有Android技术, 还有iOS, Python等文章, 可能有你想要了解的技能知识点哦~
|