享元模式
定义
Use sharing to support large numbers of fine-grained objects efficiently.
使用共享对象可有效地支持大量的细粒度的对象.
类型
结构型.
内部状态与外部状态
在享元对象内部并且不会随环境的改变而改变的共享部分, 可以称为是享元对象的内部状态, 而随环境改变而改变的, 不可以共享的状态就是外部状态了, 当然享元是可以没有内部状态的, 而外部状态最好由客户代码或者第三方类托管.
例子
Employee 接口, 抽象享元角色.
- package com.kaven.design.pattern.structural.flyweight;
- public interface Employee {
- void report();
- }
EmployeeFactory 类, 享元工厂.
- package com.kaven.design.pattern.structural.flyweight;
- import java.util.HashMap;
- import java.util.Map;
- 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.println("创建部门经理:"+department);
- String reportContent = department+"部门汇报: 此次报告的主要内容是......";
- manager.setReportContent(reportContent);
- System.out.println("创建报告:"+reportContent);
- EMPLOYEE_MAP.put(department , manager);
- }
- return manager;
- }
- }
Manager 类, 具体享元角色, 实现了 Employee 接口.
- package com.kaven.design.pattern.structural.flyweight;
- public class Manager implements Employee {
- public void report() {
- System.out.println(reportContent);
- }
- private String department;
- private String reportContent;
- public void setReportContent(String reportContent) {
- this.reportContent = reportContent;
- }
- public Manager(String department) {
- this.department = department;
- }
- }
应用层代码:
- package com.kaven.design.pattern.structural.flyweight;
- public class Test {
- private static final String departments[] = {"RD","QA","PM","BD"};
- 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();
- }
- }
- }
输出:
创建部门经理: RD
创建报告: RD 部门汇报: 此次报告的主要内容是......
RD 部门汇报: 此次报告的主要内容是......
创建部门经理: BD
创建报告: BD 部门汇报: 此次报告的主要内容是......
BD 部门汇报: 此次报告的主要内容是......
创建部门经理: PM
创建报告: PM 部门汇报: 此次报告的主要内容是......
PM 部门汇报: 此次报告的主要内容是......
PM 部门汇报: 此次报告的主要内容是......
创建部门经理: QA
创建报告: QA 部门汇报: 此次报告的主要内容是......
QA 部门汇报: 此次报告的主要内容是......
QA 部门汇报: 此次报告的主要内容是......
QA 部门汇报: 此次报告的主要内容是......
QA 部门汇报: 此次报告的主要内容是......
RD 部门汇报: 此次报告的主要内容是......
RD 部门汇报: 此次报告的主要内容是......
从结果可以看出, 已经创建出来的部门经理, 如果以后还需要使用就不需要再次创建了, 因为它已经被存储到 EmployeeFactory 类的 HashMap 中了, 因为是用 HashMap 进行存储享元的, 并且没有其他维护线程安全操作, 所以这个例子是线程不安全的.
这里便完成了一个简单的享元模式例子.
适用场景
在对象 (相同或相似的对象) 足够多的时候, 而创建这些对象造成了很大的系统开销时, 应该考虑使用享元模式.
享元有被频繁使用的场景, 才有使用享元模式的价值, 因为, 在使用享元模式的时候需要维护一个所有已经存在的享元的 key-value 数据结构, 如 HashMap(线程不安全)等, 这本身也是需要消耗系统资源的, 相当于以空间换时间.
优点
通过共享对象节约了内存资源, 降低了性能消耗.
享元模式的外部状态相对独立, 而且不会影响其内部状态, 从而使得享元对象可以在不同的环境中被共享.
缺点
享元模式需要维护一个记录了系统已有的所有享元的列表, 这本身也需要消耗资源, 在每一次使用享元使都需要进行一次查找, 这降低了程序的运行效率.
享元模式使得系统更加复杂, 需要分离出内部状态和外部状态, 这使得程序的逻辑复杂化.
如果有说错的地方, 请大家不吝赐教(记得留言哦~~~~).
来源: https://blog.csdn.net/qq_37960603/article/details/104092943