简介
为什么要使用享元模式
在系统中,有时会出现多个对象完全相同或者非常相似的情况,如果这些相似的对象过多,那么在系统运行时,将会浪费很多的资源,导致运行代价过高,性能下降等问题。享元模式就是为了解决这一问题而出现的。享元模式运用共享技术实现相同或相似对象的复用。
什么是享元模式
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。
别名
轻量级模式
类型
对象结构型模式
角色
角色
- Flyweight:抽象享元类
- 接口或抽象类
- 声明了具体享元类公共的方法。
- 提供享元对象的内部数据、设置外部数据。
- ConcreteFlyweight:具体享元类
- 具体类
- 继承或实现了抽象享元类。
- 其实例称为享元对象。
- UnsharedConcreteFlyweight:非共享具体享元类
- 具体类
- 继承或实现了抽象享元类。
- 并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类。
- FlyweightFactory:享元工厂类
- 具体类
- 享元工厂类用于创建并管理享元对象。
- 针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中,享元池一般设计为一个存储“键值对”的集合(也可以是其他类型的集合。
- 当用户请求一个具体享元对象时,享元工厂提供一个存储在享元池中已创建的实例或者创建一个新的实例(如果不存在的话),返回新创建的实例并将其存储在享元池中。
UML类图
实现
- 创建抽象享元类Flyweight.java
- 创建具体享元类ConcreteFlyweight.java
- 创建非共享具体享元类UnsharedConcreteFlyweight.java
- 创建享元工厂类FlyweightFactory.java
- 创建客户端类Client.java
抽象享元类
Flyweight.java
public interface Flyweight {
public void operation(String extrinsicState);
}
具体享元类
ConcreteFlyweight.java
public class ConcreteFlyweight implements Flyweight {
// 内部状态intrinsicState作为成员变量,同一个享元对象其内部状态是一致的
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
// 外部状态extrinsicState在使用时由外部设置,不保存在享元对象中,即使是同一个对象,在每一次调用时也可以传入不同的外部状态
@Override
public void operation(String extrinsicState) {
}
}
非共享具体享元类
UnsharedConcreteFlyweight.java
待补充
享元工厂类
FlyweightFactory.java
import java.util.HashMap;
class FlyweightFactory {
// 定义一个HashMap用于存储享元对象,实现享元池
private HashMap flyweights = new HashMap();
public Flyweight getFlyweight(String key) {
// 如果对象存在,则直接从享元池获取
if (flyweights.containsKey(key)) {
return (Flyweight) flyweights.get(key);
}
// 如果对象不存在,先创建一个新的对象添加到享元池中,然后返回
else {
Flyweight fw = new ConcreteFlyweight(key);
flyweights.put(key, fw);
return fw;
}
}
}
客户端类
Client.java
public class Client {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
Flyweight fw = factory.getFlyweight("1");
System.out.println(fw.toString());
Flyweight fw2 = factory.getFlyweight("2");
System.out.println(fw2.toString());
Flyweight fw3 = factory.getFlyweight("1");
System.out.println(fw3.toString());
}
}
测试
com.chinatvpay.flyweight.ConcreteFlyweight@a0002df
com.chinatvpay.flyweight.ConcreteFlyweight@6bc839a
com.chinatvpay.flyweight.ConcreteFlyweight@a0002df
优缺点
优点
- 享元模式可以实现对象的多次复用,在相同或相似对象较多的特殊情况下可以有效地减少内存中对象的数量。
缺点
待补充
适用环境
- 对象被多次重复使用。在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。
- 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
使用场景
待补充。
扩展
单纯享元模式
在单纯享元模式中,所有的享元对象都是可以共享的,即所有抽象享元类的子类都可共享,不存在非共享具体享元类。
复合享元模式
将一些单纯享元使用组合模式加以组合,可以形成复合享元对象,这样的复合享元对象本身不能共享,但是它们可以分解成单纯享元对象,而后者则可以共享。
问题
在软件开发中,你在哪里用到了享元模式?
待补充。