当系统中出现大量相同、相似的对象时,会导致系统性能下降。享元模式通过共享技术对相同或相似对象进行重用,从而解决这一问题。在享元模式中,存储共享实例对象的地方称为享元池 (Flyweight Pool)
享元模式(Flyweigh Pattern):运用共享技术支持大量细粒度对象的复用。又称为轻量级模式,是一种对象结构型模式
共享模式有内部状态和外部状态之分
内部状态:即存储在享元对象内部并且不会随环境而改变的状态,可以共享
外部状态:随着环境改变而改变,不可以共享的状态
享元模式结构包含如下角色
抽象享元类(Flyweight):一个接口或抽象类,该类中声明了具体享元类的公共方法
具体享元类(ConcreteFlyweight):实现了抽象享元类,其实例称为享元对象。可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一享元对象
享元工厂类(FlyweightFactory):用于创建并管理享元对象,其针对抽象享元类编程,将各种类型的具体享元类存储在一个享元池中
下面代码演示享元模式
定义抽象享元类
package com.design.structural.flyweight;
/**
* 抽象享元类
*/
public interface AbstractFlyweight {
void operation();
}
定义具体享元类
package com.design.structural.flyweight;
/**
* 具体享元类
*/
public class ConcreteFlyweight implements AbstractFlyweight{
//内部状态
private String intrinsicState;
//外部状态
private String extrinsicState;
public ConcreteFlyweight(String extrinsicState) {
this.extrinsicState = extrinsicState;
}
public void setIntrinsicState(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation() {
//业务逻辑
System.out.println(extrinsicState + ":" + intrinsicState);
}
}
定义享元工厂类
package com.design.structural.flyweight;
import java.util.HashMap;
import java.util.Map;
/**
* 享元工厂类
*/
public class FlyweightFactory {
//定义享元池容器
private static final Map<String, AbstractFlyweight> FLYWEIGHT_MAP = new HashMap<String, AbstractFlyweight>();
public static AbstractFlyweight getFlyweight(String extrinsicState){
ConcreteFlyweight concreteFlyweight = (ConcreteFlyweight) FLYWEIGHT_MAP.get(extrinsicState);
if (concreteFlyweight == null){
//根据外部状态创建享元对象
concreteFlyweight = new ConcreteFlyweight(extrinsicState);
FLYWEIGHT_MAP.put(extrinsicState, concreteFlyweight);
System.out.println("创建对象" + extrinsicState);
}
return concreteFlyweight;
}
}
类图如下
测试调用类
package com.design.structural.flyweight;
public class TestMain {
public static void main(String[] args) {
ConcreteFlyweight cf1 = (ConcreteFlyweight) FlyweightFactory.getFlyweight("X");
cf1.setIntrinsicState("内部状态1");
cf1.operation();
ConcreteFlyweight cf2 = (ConcreteFlyweight) FlyweightFactory.getFlyweight("Y");
cf2.setIntrinsicState("内部状态2");
cf2.operation();
ConcreteFlyweight cf3 = (ConcreteFlyweight) FlyweightFactory.getFlyweight("X");
cf3.setIntrinsicState("内部状态3");
cf3.operation();
}
}
调用结果如下
从调用结果可以看出:X调用两次,但只创建了一次X,实现了享元模式
享元模式总结
优点:减少内存中对象数量;减少内存之外其他资源占用,提供系统性能
缺点:使系统程序逻辑复杂;关注内部、外部状态,线程安全问题;
适用场景:系统有大量相同相似的对象;需要缓冲池的场景