6月更文挑战|设计模式 —— 享元模式

479 阅读3分钟

这是我参与更文挑战的第22天,活动详情查看:更文挑战

享元模式

享元模式可以说是对象池的一种实现,以尽可能减少内存使用,提升性能避免内存浪费。适用在使用大量重复对象的场景,通过缓存形式共享对象减少过多创造对象的目的。享元对象中可共享部分叫做内部状态,内部状态不随环境变化而变化;不可共享状态则称只为外部状态,会随着环境变化而变化。比如享元模式是一个Map容器,Key代表这享元对象的内部状态,Value则是享元对象本身。

享元模式定义: 使用共享对象来支持大量细粒度的对象。 享元模式角色:

  1. Flyweight 享元对象抽象
  2. ConcreteFlyweight 具体享元对象
  3. FlyweightFactory 享元工厂

实战

ConcreteFlyweight实现了Flyweight抽象方法后实现了自身调用方法operation。FlyweightFactory享元工厂用来保存享元对象ConcreteFlyweight集合。如同上述描述享元对象保存在Map当中,当需要创建“Window”对象时通过享元工厂去获取对应对象时会先从Map查询享元对象是否已经存在,若享元未被创建过则重新创建新对象然后将新对象保存到Map中去。在第二次获取相同标记“Window”对象时则从Map中查找取出直接使用不再需要重新创建对象了。


public abstract class Flyweight{
 public abstract void operation();
}

class ConcreteFlyweight extends Flyweight{
 private String string;
 public ConcreteFlyweight(String str){
  string = str;
 }
 public void operation(){
   ///....
 }
}

public class FlyweightFactory{
 private Hashtable flyweights = new Hashtable();
 
 public Flyweight getFlyWeight(String obj){
  Flyweight flyweight = (Flyweight) flyweights.get(obj);
  if(flyweight == null){
   flyweight = new ConcreteFlyweight(obj);
   flyweights.put(obj, flyweight);
  }
  return flyweight;
 }
}

ConcreteFlyweight fly1 = FlyweightFactory.getFlyWeight("Window");
fly1.operation();

ConcreteFlyweight fly2 = FlyweightFactory.getFlyWeight("Window");
fly2.operation();

ConcreteFlyweight fly3 = FlyweightFactory.getFlyWeight("Linux");
fly3.operation();

Android中的享元

Android源码当中的消息机制中就用运用到享元模式。Android消息机制大致是通过Handler-Message-Loop等几个类所实现的。Android通过不断的发送消息,处理 消息,销毁消息这个消息队列让进程不断工作实现系统运作。其中在getPostMessage中封装消息过程中,发现通过Message.obtain()方法返回一个Message对象,并不是通过new重新创建一个新的。对象池会将使用过处理完的Message重新回收使用,将Message中标记位置为已使用的状态,当有新消息需要被创建时会重新将回收中一些参数置覆盖成新消息内容放回到链表当中,由此达到对象池中消息池不会暴增,数量维持在合理范围内不会影响内存使用。

总结

享元模式的实现相对来说比较简单,但作用场景比较重要,尤其在对于内存使用和性能要求比较高的场景下尤为需要重视。享元模式的优点就是降低程序内存占用,增强程序性能。缺点是享元模式会使得系统复杂度提升,为了使对象共享需要将一些状态外部化增加了逻辑复杂性。