Java设计模式----享元模式(FlyWeight)

1.  享元模式定义:

     享元模式是池技术的重要实现原理,定义如下:使用共享对象可以有效的支持大量的细粒度对象

    内部状态:存储在享元对象内部不随外部环境改变可以共享出来的信息

    外部状态:外部状态是对象得以依赖的一个标记,是随外部环境改变而变化、不可以共享的状态

2.  享元模式的角色名称:

      a.  抽象享元角色

      简单地说,就是一个产品的抽象类,它同时定义了对象的内部状态和外部状态,以及接口和实现

     b. 具体的享元对象

     具体的产品类,实现了抽象产品类定义的业务

    c.  享元工厂

    提供一个池容器,同时提供从池中获取对象的方法

3.  享元模式通用示例代码:

抽象享元角色类:

public abstract class FlyWeight {
    
	//内部状态
	private String intrinsic; 
	private String name;
	//外部状态
	protected final String extrinsic;
	
	//要求享元角色必须接受外部状态
	public FlyWeight(String extrinsic) {
		this.extrinsic=extrinsic;
	}
	
	//定义业务操作
	public abstract void  operator();
    
	//内部状态的getter/setter
	public String getIntrinsic() {
		return intrinsic;
	}

	public void setIntrinsic(String intrinsic) {
		this.intrinsic = intrinsic;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
		
}
抽象享元角色类一般是一个抽象类,一般要把外部状态和内部状态定义出来,避免子类随意的扩展。

具体的享元角色类:

public class FlyWeight1 extends FlyWeight{
   
	public FlyWeight1(String extrinsic) {
		super(extrinsic);
	}

	@Override
	public void operator() {
		
		System.out.println("业务操作方法...内部状态是:"+super.getIntrinsic());
		
	}
}
享元工厂类:

public class FlyWeightFactory {
   
	private static HashMap<String,FlyWeight> pool=new HashMap<String,FlyWeight>();
	
	public static  FlyWeight getInstance(String key){
		//需要返回的对象
		FlyWeight flyWeight=null;
		//如果池中存在该对象,直接获取返回
		if(pool.containsKey(key)){
			System.out.println(key+"-----池中存在,直接从对象池中取得");
			flyWeight=pool.get(key);
		}else{
			//池中不存在此对象,根据外部状态新建一个对象返回
			System.out.println(key+"-----池中不存在,建立对象并放到对象池中");
			flyWeight=new FlyWeight1(key);
			//放置到池中
			pool.put(key, flyWeight);
		}
		return flyWeight;
	}
	
	/**
	 * 初始化对象池
	 * @param size
	 */
	public static void initObjectPool(int size){
		for (int i = 0; i <= size; i++) {
			FlyWeightFactory.getInstance("对象"+i);
		}
	}
}
测试类:

public class Test {
   
	public static void main(String[] args) {
		//初始化对象池
		FlyWeightFactory.initObjectPool(4);
		FlyWeight flyWeight=FlyWeightFactory.getInstance("对象1");
		flyWeight.setIntrinsic("这是单独设置的内部状态!");
		flyWeight.operator();
	}
}
结果:

对象0-----池中不存在,建立对象并放到对象池中
对象1-----池中不存在,建立对象并放到对象池中
对象2-----池中不存在,建立对象并放到对象池中
对象3-----池中不存在,建立对象并放到对象池中
对象4-----池中不存在,建立对象并放到对象池中
对象1-----池中存在,直接从对象池中取得
业务操作方法...内部状态是:这是单独设置的内部状态!
4.   享元模式的优点和缺点

      享元模式是可以大大减少应用程序创建对象的时间,降低程序内存的占用,增强程序的性能,同时它也大大加大了程序的复杂度,因为需要分离外部状态和内部状态。

5.  享元模式的使用场景

          在如下场景中则可以选择使用享元模式。

● 系统中存在大量的相似对象。

● 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份。

● 需要缓冲池的场景。

6.  享元模式的线程安全问题:

     由于使用的是共享对象,所以很可能会出现2个线程共用一个对象并且同时修改的问题,这样就会出现线程安全问题。为了尽可能避免这个问题,要尽量的加大对象池中对象的数量,并且对于外部状态,最好可以使用多个字符串的组合来确定key值(即对象池中,一个对象对应一个key值)







原文地址:https://www.cnblogs.com/elgin-seth/p/5293763.html