二十三种设计模式分类
一、概述
享元(Flyweight
)模式的定义:运用共享技术来有効地支持大量细粒度对象的复用。它通过共享已经存在的又橡来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
主要解决在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
优点
相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
缺点
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
场景
1、系统有大量相似对象。
2、需要缓冲池的场景。
二、实现
享元模式中存在以下两种状态:
- 内部状态,即不会随着环境的改变而改变的可共享部分;
- 外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。
1. 结构图
享元模式的主要角色有如下。
- 抽象享元角色(
Flyweight
):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。 - 具体享元(
Concrete Flyweight
)角色:实现抽象享元角色中所规定的接口。 - 非享元(
Unsharable Flyweight
)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。 - 享元工厂(
Flyweight Factory
)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
PS
:UML
结构图可以参考,例子实现并不根据UML
图来完成,灵活实现即可;
2. 实现
- 连接池类
package cn.missbe.model.flyweight;
import java.util.ArrayList;
import java.util.List;
/**
* Copyright (c) 2020.
* Email: love1208tt@foxmail.com
* @author lyg 2020/4/28 上午11:11
* description:
* 享元模式:重复利用对象
* 数据库连接池,维护数据库连接重复利用创建的连接
**/
public class DatasourceConnectionPool {
private List<DatasourceConnection> connections = new ArrayList<>();
public synchronized DatasourceConnection getConnection(){
for (DatasourceConnection datasourceConnection : connections) {
///找一个不繁忙的连接
if (!datasourceConnection.isBusy()) {
return datasourceConnection;
}
}
DatasourceConnection connection = new DatasourceConnection();
connections.add(connection);
return connection;
}
public void register(DatasourceConnection connection) {
this.connections.add(connection);
}
public int size(){
return this.connections.size();
}
}
- 连接类
package cn.missbe.model.flyweight;
/**
* Copyright (c) 2020.
* Email: love1208tt@foxmail.com
* @author lyg 2020/4/28 上午11:10
* description:
* 模拟数据库连接对象
**/
public class DatasourceConnection {
/**数据库连接对象*/
private Object datasourceConnection;
/**该连接是否繁忙*/
private boolean isBusy;
public DatasourceConnection() {
this("datasourceConnection", false);
}
public DatasourceConnection(Object datasourceConnection, boolean isBusy) {
this.datasourceConnection = datasourceConnection;
this.isBusy = isBusy;
}
public Object getDatasourceConnection() {
return datasourceConnection;
}
public void setDatasourceConnection(Object datasourceConnection) {
this.datasourceConnection = datasourceConnection;
}
public boolean isBusy() {
return isBusy;
}
public void setBusy(boolean busy) {
isBusy = busy;
}
public void simulateProcessingTasks(){
///开始处理任务,不能再被别的重用
this.isBusy = true;
System.out.println("Before Processing:" + this);
try {
///模拟任务处理
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
///处理完成,可以再次使用
isBusy = false;
System.out.println("After Processing:" + this);
}
@Override
public String toString() {
return "DatasourceConnection{" + "datasourceConnection=" + datasourceConnection + ", isBusy=" + isBusy + '}';
}
}
- 主类
package cn.missbe.model.flyweight;
/**
* Copyright (c) 2020.
* Email: love1208tt@foxmail.com
* @author lyg 2020/4/28 上午11:18
* description:
* 享元模式:重复利用创建的对象,String的常量池/数据库连接池都采用此种思想
**/
public class Main {
@SuppressWarnings("all")
public static void main(String[] args) throws InterruptedException {
DatasourceConnectionPool pool = new DatasourceConnectionPool();
for (int i = 0; i < 5; i++) {
pool.register(new DatasourceConnection("datasourceConnection:"+i,false));
}
for (int i = 0; i < pool.size(); i++) {
new Thread(()->{
pool.getConnection().simulateProcessingTasks();
}).start();
///当前线程睡眠,等待连接处理完任务测试重复使用创建的对象
Thread.sleep(1000);
}
}
}