概述
- 定义 : 提供了减少对象数量从而改善应用所需的对象结构的方式
- 运用共享技术有效的支持大量细粒度的对象
- 类型 : 结构型
适用场景
- 常常应用于系统底层的开发, 以便解决系统的性能问题
- 系统有大量相似的对象, 需要缓冲池的场景
优点
- 减少对象的创建, 降低内存中对象的数量, 降低系统的内存, 提高效率
- 减少内存之外的其他资源占用
缺点
- 关注内/外部状态, 关注线程安全问题
- 使系统, 程序的逻辑复杂化
扩展
- 内部状态
- 外部状态
模式角色
-
Flyweight : 描述一个接口,通过这个接口f l y w e i g h t可以接受并作用于外部状态
-
ConcreteFlyweight : 实 现 F l y w e i g h t 接 口 , 并 为 内 部 状 态 ( 如 果 有 的 话 ) 增 加 存 储 空 间 。
ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的;即,它必
须独立于 ConcreteFlyweight对象的场景。 -
UNsharedConcreteFlyweight : 并非所有的F l y w e i g h t子类都需要被共享。 F l y w e i g h t接口使共享成为可能,但它并不强制共享。在F l y w e i g h t对象结构的某些层次, U n s h a r e d C o n c r e t e F l y w e i g h t对象通常将C o n c r e t e F l y w e i g h t对象作为子节点
-
FlyweightFactory
- 创建并管理Flyweight 对象。
- 确保合理地共享Flyweight当用户请求一个Flyweight 时,F l y w e i g h t F a c t o r y对象提供一个已创建的实例或者创建一个(如果不存在的话)。
-
Client
- 维持一个对Flyweight 的引用。
- 计算或存储一个(多个)Flyweight 的外部状态。
代码实现
场景:
1.有一个员工接口Employee, 对应Flyweight接口
2.部门经理类Manger实现了员工接口, 对应ConcreteFlyweight接口实现
3. 一个EmployeeFactory类用于管理Employee, 对应FlyweightFactory
4. 场景就是部门经理做年终报告
代码如下 :
/**
* Flyweight角色
*
* @author 七夜雪
* @create 2018-11-23 18:52
*/
public interface Employee {
void report();
}
/**
* ConcreteFlyweight 角色
* @author 七夜雪
*/
public class Manager implements Employee {
@Override
public void report() {
System.out.println(reportContent);
}
// 这个就是内部状态
private String title = "部门经理";
private String department;
private String reportContent;
public void setReportContent(String reportContent) {
this.reportContent = reportContent;
}
public Manager(String department) {
this.department = department;
}
}
/**
* FlyweightFactory角色
*
* @author 七夜雪
* @create 2018-11-23 14:07
*/
public class EmployeeFactory {
private static final Map<String,Employee> EMPLOYEE_MAP = new HashMap<String,Employee>();
public static Employee getManager(String department){
Manager manager = (Manager) EMPLOYEE_MAP.get(department);
if(manager == null){
manager = new Manager(department);
System.out.print("创建部门经理:"+department);
String reportContent = department+"部门汇报:此次报告的主要内容是......";
manager.setReportContent(reportContent);
System.out.println(" 创建报告:"+reportContent);
EMPLOYEE_MAP.put(department,manager);
}
return manager;
}
}
测试代码:
public static void main(String[] args) {
for(int i=0; i<10; i++){
String department = departments[(int)(Math.random() * departments.length)];
Manager manager = (Manager) EmployeeFactory.getManager(department);
manager.report();
}
}
测试结果:
创建部门经理:测试 创建报告:测试部门汇报:此次报告的主要内容是…
测试部门汇报:此次报告的主要内容是…
创建部门经理:开发 创建报告:开发部门汇报:此次报告的主要内容是…
开发部门汇报:此次报告的主要内容是…
创建部门经理:人力 创建报告:人力部门汇报:此次报告的主要内容是…
人力部门汇报:此次报告的主要内容是…
创建部门经理:产品 创建报告:产品部门汇报:此次报告的主要内容是…
产品部门汇报:此次报告的主要内容是…
人力部门汇报:此次报告的主要内容是…
产品部门汇报:此次报告的主要内容是…
开发部门汇报:此次报告的主要内容是…
人力部门汇报:此次报告的主要内容是…
开发部门汇报:此次报告的主要内容是…
人力部门汇报:此次报告的主要内容是…
从测试结果来看, 只有第一次使用时才创建了Manager对象, 其余都是直接从Map中获取了, 这就是享元模式的概念