前言
本文代码是以BeanCopier为题材实现的,意在给BeanCopier加一层缓存。但是!!!这个做法是多余的,因为BeanCopier自带了缓存功能,由于刚接触BeanCopier不久,所以干了这件傻事,不过代码对于学习享元模式还是可以的,所以贴了出来,但是不可用于实际工作哦。
说明
享元模式(Flyweight Pattern)是一种结构型模式,主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
应用场景
- 系统中存在大量的相似对象
- 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份
- 需要缓冲池的场景
模式特征
角色 | 说明 | 举栗 |
---|---|---|
Flyweight 抽象享元角色 | 简单地说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现 | CopierHolder |
ConcreteFlyweight 具体享元角色 | 具体的一个产品类, 实现抽象角色定义的业务. 该角色需要注意的是内部状态处理应该与环境无关,不应该初恋一个操作改变了内部状态,同时修改了外部状态, 这是角色不允许的 | SimpleCopierHolder |
FlyweightFactory 享元工厂 | 职责非常简单, 就是构造一个池容器,同时提供从池中获得对象的方法 | CopierFactory |
代码实现
代码场景:使用BeanCopier工具进行对象属性拷贝,从OriginBean拷贝到TargetBean,(一开始我以为BeanCopier没有缓存,因为没看源码)而且刚学享元模式,所以想通过享元模式给BeanCopier加一层缓存功能,但是刚写完代码,就想到BeanCopier应该是有缓存的,一看源码,果不其然,心里那个气哦T.T
关于BeanCopier可了解:
1.封装BeanCopier工具,支持单个对象以及列表拷贝,超高性能简单实用
2.各类对象属性拷贝工具性能测试对比(BeanCopier、BeanUtils、DozerBeanMapper、PropertyUtils)
- 抽象享元角色
public abstract class CopierHolder {
//内部状态
protected BeanCopier beanCopier;
/**
* 源对象类型(外部状态)
*/
protected Class source;
/**
* 目标对象类型(外部状态)
*/
protected Class target;
public CopierHolder(Class source, Class target) {
this.source = source;
this.target = target;
}
/**
* 创建BeanCopier
*/
public abstract void createCopier();
}
- 具体享元角色
public class SimpleCopierHolder extends CopierHolder {
public SimpleCopierHolder(Class source, Class target) {
super(source, target);
}
@Override
public void createCopier() {
this.beanCopier = BeanCopier.create(this.source, this.target, false);
}
}
- 享元工厂
public class CopierFactory {
//定义一个容器
private static Map<Map<Class, Class>, CopierHolder> pool = new HashMap<>();
//获取BeanCopier
public static BeanCopier getBeanCopier(Class source, Class target) {
Map<Class, Class> keyMap = new HashMap<>();
keyMap.put(source, target);
CopierHolder copierHolder;
if (pool.containsKey(keyMap)) {
copierHolder = pool.get(keyMap);
} else {
copierHolder = new SimpleCopierHolder(source, target);
copierHolder.createCopier();
pool.put(keyMap, copierHolder);
}
return copierHolder.beanCopier;
}
}
- 客户端测试
public class Client{
public static void main(String[] args){
//函数getBeanCopier就是支持缓存的,如果存在则直接返回,不存在则会进行创建
BeanCopier copier = CopierFactory.getBeanCopier(OriginBean.class, Target.class);
}
}
优缺点
优点
大大减少对象的创建,降低系统的内存,使效率提高。
缺点
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。