享元模式是池技术的重要实现方式,其定义如下:
Use sharing to support large numbers of fine-grained objects efficiency.
使用共享对象可有效的支持大量的细粒度的对象
享元模式的定义为我们提出了两个要求:细粒度的对象和共享对象
细粒度对象使用的数量多且性质相近,那么就需要将这些对象的信息分为两个部分:内部状态(intrinsic)和外部状态(extrinsic)
内部状态:就是对象中可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变
外部状态:就是对象得以依赖的一个标记,是随环境改变而改变的,不可以共享的状态
享元模式角色:
Flyweight抽象享元角色:就是一个产品的抽象类,同事定义出对象的外部状态和内部状态的接口或实现
ConcreteFlyweight具体享元角色:具体的一个产品类,实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与
环境无关,不应该出现一个操作改变了内部状态。同事修改了外部状态
unsharedConcreteFlyweight不可共享的享元角色:不存在外部状态或安全要求(如线程安全)不能够使用共享技术的对象,该对象
一般不会出现在享元工厂中。
FlyweightFactory享元工厂:职责非常简单就是构造一个池容器,同时提供从池中获得对象的方法
//抽象享元角色 public abstract class Flyweight{ //内部状态 private String intrinsic; //外部状态 private final String Extrinsic; //将外部状态定义为final,是为了防止意外产生,防止无意中修改导致池混乱 /* 注意:在程序开发中,确认只需要一次赋值的属性则设置为final类型,避免无意修改导致逻辑混乱,特别是Session 级的常量或变量 */ //要求享元角色必须接受外部状态 public Flyweight(String _extrinsic){ this.Extrinsic=_extrinsic; } //定义业务操作 public abstract void operate(); //内部状体的getter/setter public String getIntrinsic(){ return intrinsic; } public void setIntrinsic(String intrinsic){ this.intrinsic=intrinsic; } } //具体享元角色 public class ConcreteFlyweight1 extends Flyweight{ //接受外部状态 public ConcreteFlyweight1(String _extrinsic){ super(_extrinsic); } //根据外部状体进行逻辑处理 public void operate(){ } } public class ConcreteFlyweight2 extends Flyweight{ //接受外部状态 public ConcreteFlyweight2(String _extrinsic){ super(_extrinsic); } //根据外部状体进行逻辑处理 public void operate(){ } } //享元工厂 public class FlyweightFactory{ //定义一个池容量 private static HashMap<String,Flyweight> pool=new HashMap<String,Flyweight>(); //享元工厂 public static Flyweight getFlyweight(String extrinsic){ //需要返回的对象 Flyweight flyweight=null; //在池中没有该对象 if(pool.containKey(extrinsic)){ flyweight=pool.get(extrinsic); }else{ //根据外部状态创建享元对象 flyweight=new ConcreteFlyweight1(extrinsic); //放置到池中 pool.put(extrinsic,flyweight); } return flyweight; } }
享元模式的优点和缺点:
享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存占用,增强程序的性能,但它同时也提高
了系统复杂性,需要分离外部状体和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变。否则导致系统的逻辑混乱
使用场景:
1.系统中存在大量的相似对象
2.细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份
3.需要缓冲池的场景