设计模式——享元模式

86 阅读2分钟

一.定义

    使用共享对象可有效地支持大量细粒度的对象。

  • 细粒度的对象
  • 共享对象

二.类图

image.png

  • Flyweight抽象享元角色。简单说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。
  • ConcreteFlyweight具体享元角色。具体的一个产品类,实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是绝对不允许的。
  • UnsharedConcreteFlyweight不可共享的享元角色。不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。
  • FlyweightFactory享元工厂。构造一个池容器,同时提供从池中获得对象的方法。

三.优点

    大大减少应用程序创建的对象,降低程序内存占用,增强了程序性能。

四.缺点

    提高了系统复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该内状态改变而改变,否则导致系统的逻辑混乱。

五.应用场景

  • 系统中存在大量的相似对象。
  • 细粒度的对象都具备较接近的外部状态,且内部状态与环境无关,也就是说对象没有特定身份。
  • 需要缓冲池的场景。

六.注意事项

  • 线程安全问题。享元对象数量太少,多线程情况下每个线程都到对象池中获得对象,然后都去修改其属性,于是就出现一些问题。享元模式让我们使用共享技术,Java多线程使用会提高效率但会带来安全问题,如何设计来避免没有标准答案,只有依靠经验,在需要的地方考虑一下线程,在大部分的场景下都不用考虑。同时,在使用享元模式时,对象池中的享元对象尽量多,多到足够满足业务为止。
  • 注意性能平衡。尽量使用Java基本类型作为外部状态,效率会比使用复合对象高很多。
  • 享元模式可以实现对象池,但两者还是有比较大的区别的。对象池着重在对象的复用上,池中每个对象是可替换的,从同一个池中获得A对象和B对象对客户端来说是完全相同的,它主要解决复用,而享元模式主要解决的是对象的共享问题,如何建立多个可共享的细粒度对象则是其关注的重点。