Java 设计模式系列(十一)享元模式
一、享元模式的结构
享元模式采用一个共享来避免大量拥有相同内容对象的开销。这种开销最常见、最直观的就是内存的损耗。享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)。
一个内部状态是存储在享元对象内部的,并且是不会随环境的改变而有所不同。因此,一个享元可以具有内蕴状态并可以共享。
一个外部状态是随环境的改变而改变的、不可以共享的。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内部状态,它们是相互独立的。
Flyweight
:享元接口,通过这个接口 flyweight 可以接受并作用于外部状态。通过这个接口传入外部的状态,在享元对象的方法处理中可能会使用这些外部的数据。ConcreteFlyweight
:具体的享元实现对象,必须是可共享的,需要封装 flyweight 的内部状态。FlyweightFactory
:享元工厂,主要用来创建并管理共享的享元对象,并对外提供访问共享享元的接口。
源代码
(1) Flyweight
/***
* 享元接口,通过这个接口享元可以接受并作用于外部状态
*/
public interface Flyweight {
/** 示例操作,传入外部状态 */
public void operation(String extrinsicState);
}
public class ConcreteFlyweight implements Flyweight{
/** 示例,描述内部状态 */
private String intrinsicState;
/** 构造方法,传入享元对象的内部状态的数据 */
public ConcreteFlyweight(String state){
this.intrinsicState = state;
}
public void operation(String extrinsicState) {
//具体的功能处理,可能会用到享元内部、外部的状态
}
}
(2) FlyweightFactory
/**
* 享元工厂,说白了就是一个缓存
*/
public class FlyweightFactory {
/** 缓存多个flyweight对象,这里只是示意一下 */
private Map<String, Flyweight> fsMap = new HashMap<String,Flyweight>();
/** 获取key对应的享元对象 */
public Flyweight getFlyweight(String key) {
//这个方法里面基本的实现步骤如下:
//1:先从缓存里面查找,是否存在key对应的Flyweight对象
Flyweight f = fsMap.get(key);
//2:如果存在,就返回相对应的Flyweight对象
if(f == null){
//3:如果不存在
//3.1:创建一个新的Flyweight对象
f = new ConcreteFlyweight(key);
//3.2:把这个新的Flyweight对象添加到缓存里面
fsMap.put(key, f);
//3.3:然后返回这个新的Flyweight对象
}
return f;
}
}
二、总结
(1) 享元模式的优缺点
享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:
享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
每天用心记录一点点。内容也许不重要,但习惯很重要!