享元模式

定义

        提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效的支持大量细粒度的对象。简而言之,就是将类的通用属性抽出来,建立对象池,以达到限制对象数量的效果;一般用在需要多次创建对象的情况,如线程池、String常量池、数据库连接池、缓冲池等等。

适用场景

  • 常常应用于系统底层的开发,以便解决系统新能问题
  • 系统有大量相似对象,需要缓冲池的场景

例如如果一个系统存在大量细粒度对象,且这些对象的状态都可以外部化,就可以使用享元模式。下面是外部化和内部化的解释:

  • 内部状态指对象共享出来的信息,存储在享元对象内部并且不会随环境的改变而改变;
  • 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。

优点

大大减少了对象的创建,降低了程序内存的占用,提高效率

缺点

提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变

UML类图

  • Flyweight是抽象享元角色。它是产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现;
  • ConcreteFlyweight是具体享元角色,是具体的产品类,实现抽象角色定义的业务;
  • UnsharedConcreteFlyweight是不可共享的享元角色,一般不会出现在享元工厂中;
  • FlyweightFactory是享元工厂,它用于构造一个池容器,同时提供从池中获得对象的方法。

 

代码演示

以职员做报告为例,每个部门都需要做报告,如果每次需要报告都要new一个报告,就会产生大大的减少性能。所以我们就可以用一个报告池专门用来让职员获取报告。

 这里报告工厂就是享元工厂,报告就是抽象享元角色,不同的报告就是具体享元角色,在报告中固定不变的属性就是内部状态,需要改变的属性就是外部属性。

  • 抽象Report类(Flyweight)
public abstract class Report {
    //内部状态
    private String content;
    //外部状态
    private final String department;

    //要求享元角色必须接受外部状态
    public Report(String department) {
      this.department = department;
      this.content = "部门报告";
   }

    //定义业务操作
    public abstract void operate();

    public String getContent() {
      return content;
    }
}
  • 具体Report类(ConcreteFlyweight)
public class ConcreteReport extends Report {

    public ConcreteReport(String department) {
        super(department);
    }

    @Override
    public void operate() {
        System.out.println(super.getContent);
    }
}
  • ReportFactory(FlyweightFactory)
public class ReportFactory {
    private final static Map<String,Report> map = new HashMap<>();

    public Report getReport(String department){
        Report report = map.get(department);
        if (report == null){
            report = new ConcreteReport(department);
            map.put(department,report);
        }
        return report;
    }
}

源码的应用

Integer类

 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            ...
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

可以看到如果i的值-128和127时,默认会去缓存池中获取,如果超过才会new一个返回,这里就用到了享元模式。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值