Java设计模式(十一) 系统优化利器——享元模式

 

大部分设计模式提供了很好的扩展性和灵活性,而享元模式通过实现对象的共享,减少了内存使用,降低了对象创建和垃圾回收的开销,从而提升了系统性能...




点击上方

大数据架构 快速关注
单例模式
本文介绍了享元模式的适用场景,并结合实例详述了享元模式的实现方式。最后分析了享元模式的优缺点及已(未)遵循的OOP原则。

享元模式适用场景

面向对象技术可以很好的解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致对象创建及垃圾回收的代价过高,造成性能下降等问题。享元模式通过共享相同或者相似的细粒度对象解决了这一类问题。

享元模式定义

享元模式(Flyweight Pattern),又称轻量级模式(这也是其英文名为FlyWeight的原因),通过共享技术有效地实现了大量细粒度对象的复用。

享元模式类图

享元模式类图如下(点击查看大图)



享元模式角色划分

  • FlyWeight 享元接口或者(抽象享元类),定义共享接口
  • ConcreteFlyWeight 具体享元类,该类实例将实现共享
  • UnSharedConcreteFlyWeight 非共享享元实现类
  • FlyWeightFactory 享元工厂类,控制实例的创建和共享


内部状态 vs. 外部状态

  •  内部状态是存储在享元对象内部,一般在构造时确定或通过setter设置,并且不会随环境改变而改变的状态,因此内部状态可以共享。
  •  外部状态是随环境改变而改变、不可以共享的状态。外部状态在需要使用时通过客户端传入享元对象。外部状态必须由客户端保存。


享元模式实例解析

享元接口,定义共享接口

package com.jasongj.flyweight;

public interface FlyWeight {

void action(String externalState);

}

具体享元类,实现享元接口。该类的对象将被复用

package com.jasongj.flyweight;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class ConcreteFlyWeight implements FlyWeight {

private static final Logger LOG = LoggerFactory.getLogger(ConcreteFlyWeight.class);

private String name;

public ConcreteFlyWeight(String name) {

this.name = name;

}

@Override

public void action(String externalState) {

LOG.info("name = {}, outerState = {}", this.name, externalState);

}

}

享元模式中,最关键的是享元工厂。它将维护已创建的享元实例,并通过实例标记(一般用内部状态)去索引对应的实例。当目标对象未创建时,享元工厂负责创建实例并将其加入标记-对象映射。当目标对象已创建时,享元工厂直接返回已有实例,实现对象的复用。



从上面代码中可以看到,享元模式中对象的复用完全依靠享元工厂。同时本例中实现了对象创建的懒加载。并且为了保证线程安全及效率,本文使用了双重检查(Double Check)。

本例中,name可以认为是内部状态,在构造时确定。externalState属于外部状态,由客户端在调用时传入。

享元模式优点

  • 享元模式的外部状态相对独立,使得对象可以在不同的环境中被复用(共享对象可以适应不同的外部环境)
  • 享元模式可共享相同或相似的细粒度对象,从而减少了内存消耗,同时降低了对象创建与垃圾回收的开销
享元模式缺点

  • 外部状态由客户端保存,共享对象读取外部状态的开销可能比较大
  • 享元模式要求将内部状态与外部状态分离,这使得程序的逻辑复杂化,同时也增加了状态维护成本
享元模式遵循的OOP原则

  •  依赖倒置原则
  •  迪米特法则
  •  里氏替换原则
  •  接口隔离原则
  •  单一职责原则
  •  开闭原则
本文代码可从作者Github下载

https://github.com/habren/JavaDesignPattern/tree/master/FlyweightPattern/src/main

设计模式系列文章

  • Java设计模式(一) 简单工厂模式不简单
  • Java设计模式(二) 工厂方法模式
  • Java设计模式(三) 抽象工厂模式
  • Java设计模式(四) 观察者模式
  • Java设计模式(五) 组合模式
  • Java设计模式(六) 代理模式 vs. 装饰模式
  • Java设计模式(七) Spring AOP JDK动态代理 vs. cglib
  • Java设计模式(八) 适配器模式
  • Java设计模式(九) 桥接模式
  • Java设计模式(十) 你真的用对单例模式了吗
版权声明


原创文章,始发自作者个人博客www.jasongj.com。转载请在文章开头处注明转自【大数据架构】并以超链接形式注明原文链接http://www.jasongj.com/design_pattern/flyweight/
长按下方二维码可快速关注
点击“阅读全文”,查看作者个人博客
↓↓


    关注 大数据架构


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册