DesignPattern - 享元模式【结构型】
# 一、享元模式介绍
享元模式(Flyweight Pattern)属于结构型模式,主要用于减少创建对象的数量,以减少内存占用和提高性能,它提供了减少对象数量从而改善应用所需的对象结构的方式;享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
状态
- 内部状态:不会随环境的改变而所有不同,是可以共享的
- 外部状态:它随环境的改变而改变的,是不可以共享的,因此外部状态是由客户端来保持(因为环境的变化一般是由客户端引起)
核心组成
- 抽象享元角色:为具体享元角色规定了必须实现的方法,而外部状态就是以参数的形式通过些方法传入
- 具体享元角色:实现抽象角色规定的方法,如果存在内部状态,就负责为内部状态提供存储空间
- 享元工厂角色:负责创建和管理享元角色。(要想达到共享的目的,这个角色很关键)
- 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外部状态
应用场景
- Java 中的 String,如果字符串常量池里有则返回,如果没有则创建一个字符串保存在字符串常量池里
- 数据库连接池、线程池等
- 如果系统有大量相似的对象,或者需要用缓冲池的时候可以使用享元模式,也就是大家常说的池化技术
- 如果发现某个对象生成了大量细粒度的实例,并且这些实例除了几个参数外基本是相同的,如果把那些共享参数移到类外面,在方法调用时将他们传递进来,就可以通过共享对象,减少实例的个数
优点
- 大大减少了对象的创建,降低了程序内存的占用,提高效率
缺点
- 提高了系统的复杂度,需要分离出内部状态和外部状态
注意划分内部状态和外部状态,否则可能会引起线程安全问题,必须有一个工厂类加以控制
# 二、享元模式代码实现
创建 抽象享元角色,规定具体享元角色必须实现的方法:
/**
* 抽象享元角色:sql数据库连接
*
* @author GitLqr
*/
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
是外部状态
创建 具体享元角色:
/**
* 具体享元角色:Mysql数据库连接
*
* @author GitLqr
*/
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;
}
}
/**
* 具体享元角色:Oracle数据库连接
*
* @author GitLqr
*/
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;
}
}
创建 享元工厂角色:
注意:这个工厂类是享元模式的核心,由它管理所有享元对象
/**
* 享元工厂角色:sql连接工厂类
*
* @author GitLqr
*/
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;
}
}
}
- 01
- Flutter - 危!3.24版本苹果审核被拒!11-13
- 02
- Flutter - 轻松搞定炫酷视差(Parallax)效果09-21
- 03
- Flutter - 轻松实现PageView卡片偏移效果09-08