模式定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类(取自《设计模式之禅》)。
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
通用类图如下(可能有不同版本,本文中仿照这个版本):
AbstractProductA,AbstractProductB.....无限扩展,具体实现的子类为ProductA1,ProductA2...也是无限扩展,不管是产品类型维度和具体现实类都是可以动态扩展的,最后由AbstractCreator工厂的具体实现工厂类创建对象。
需求如下,
1.前端需要展现Echarts图表,后台接口提供json数据对象;
2.一个类可以实现和使用多种图表;
3.后期图表封装的工具类可以进行动态的扩展(及图表扩展)而不需要增加和修改很多代码;
echarts官网json对象截图
痛点如下:
故选用抽象工厂模式,图1.1中不同的产品类型正好对应Echarts中不同的图表类型,productA对应柱状图,productB对应折线图等等;工厂模式很好的解决了问题2和问题3,而模板模式又很好的解决了问题1,完美。
模板模式传送门:https://blog.csdn.net/xiewenfeng520/article/details/83278250
项目类图如下
EchartsFactory为顶层的工厂抽象类,定义工厂需要创建对象的抽象方法。
DefaultEchartsFactory继承EchartsFactory,是具体方法的工厂实现类。
AbstractBarSimple和AbstractLineSimple为不同图表产品的抽象父类,而BarSimpleImpl1,BarSimpleImpl2....为具体业务实现。
BsaeEchartsBean为顶层的图表对象抽象类,定义图表的公告抽象方法。
核心代码如下:
抽象工厂类 EchartsFactory:
package com.huajie.service.echarts;
import java.util.Map;
/**
* @author xiewenfeng Echarts抽象工厂
*/
public abstract class EchartsFactory {
public abstract AbstractBarSimple createBarSimple(Map parameters, Class> cls);
public abstract AbstractLineSimple createLineSimple(Map parameters, Class> cls);
}
具体工厂实现类 DefaultEchartsFactory:
package com.huajie.service.echarts;
import java.lang.reflect.Method;
import java.util.Map;
import org.springframework.beans.BeansException;
import com.huajie.utils.Spring.SpringUtils;
public class DefaultEchartsFactory extends EchartsFactory {
@Override
public AbstractBarSimple createBarSimple(Map parameters, Class> cls) {
return (AbstractBarSimple)getBeanInstance(cls,parameters);
}
@Override
public AbstractLineSimple createLineSimple(Map parameters, Class> cls) {
return (AbstractLineSimple)getBeanInstance(cls,parameters);
}
@SuppressWarnings("unchecked")
public static T getBeanInstance(Class cls,Map parameters) throws BeansException {
try {
/**
* 如果使用反射newInstance()之后
* cls实现类springIOC容器失效
* 所以从SpringIOC容器中获取该实例
*/
Object obj = SpringUtils.getBeanByName(cls);
Method method = cls.getDeclaredMethod("setParameters", new Class[] { Map.class });
method.setAccessible(true);
method.invoke(obj, parameters);
return (T)obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
BsaeEchartsBean:
package com.huajie.service.echarts;
import java.util.Map;
/**
* @author xiewenfeng
*/
public abstract class BsaeEchartsBean{
protected Map parameters;
protected abstract void setParameters(Map parameters);
protected abstract T initEchartsData() ;
}
AbstractLineSimple:
package com.huajie.service.echarts;
import java.util.ArrayList;
import java.util.List;
import com.huajie.entity.echarts.ExtMapData;
import com.huajie.entity.echarts.LineSimple;
/**
* @author xiewenfeng 封装后台echarts 图表数据组合 LineSimple折线图
*/
public abstract class AbstractLineSimple extends BsaeEchartsBean{
/**
* 获取data数据集
* name :x轴值集合
* value :对应的y轴值集合
* ExtMapData 的List集合形式
* @return
*/
protected abstract List> ListXYAxis();
public LineSimple initEchartsData() {
LineSimple lineSimple = new LineSimple();
List xAxisDataList = new ArrayList();
List seriesDataList = new ArrayList();
List> listData = ListXYAxis();
for (ExtMapData extMapData : listData) {
xAxisDataList.add(String.valueOf(extMapData.getName()));
seriesDataList.add(String.valueOf(extMapData.getValue()));
}
lineSimple.setXAxisData(xAxisDataList);
lineSimple.setSeriesData(seriesDataList);
return lineSimple;
}
}
AbstractBarSimple:
package com.huajie.service.echarts;
import java.util.ArrayList;
import java.util.List;
import com.huajie.entity.echarts.BarSimple;
import com.huajie.entity.echarts.ExtMapData;
/**
* @author xiewenfeng
* 封装后台echarts 图表数据组合
* BarSimple柱状图
*/
public abstract class AbstractBarSimple extends BsaeEchartsBean{
protected abstract List getLegendList();
/**
* 获取data数据集
* name :x轴值集合
* value :对应的y轴值集合
* ExtMapData 的List集合形式
* @return
*/
protected abstract List> ListXYAxis();
public BarSimple initEchartsData() {
BarSimple barSimple = new BarSimple();
List legendList = getLegendList();
List> listData = ListXYAxis();
List xAxisDataList = new ArrayList();
List
对应业务实现类(每个项目根据自身需求同步,对应现实类不同)
BarSimpleImpl
package com.huajie.service.impl.echarts.LeadergroupTotalAnalysis;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.huajie.entity.echarts.ExtMapData;
import com.huajie.mapper.report.LeadergroupTotalAnalysisMapper;
import com.huajie.service.echarts.AbstractBarSimple;
/**
* @author xiewenfeng 总体分析柱状图
*/
@Service
public class BarSimpleImpl extends AbstractBarSimple {
@Autowired
private LeadergroupTotalAnalysisMapper leadergroupTotalAnalysisMapper;
@Override
protected void setParameters(Map parameters) {
super.parameters = parameters;
}
@Override
protected List getLegendList() {
List legendList = new ArrayList();
legendList.add("分数");
return legendList;
}
@Override
protected List> ListXYAxis() {
return leadergroupTotalAnalysisMapper.getLeadergroupQuotaDistribute(parameters);
}
}
LineSimpleImpl
package com.huajie.service.impl.echarts.LeadergroupTotalAnalysis;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.huajie.entity.echarts.ExtMapData;
import com.huajie.mapper.report.LeadergroupTotalAnalysisMapper;
import com.huajie.service.echarts.AbstractLineSimple;
@Service
public class LineSimpleImpl extends AbstractLineSimple {
@Autowired
private LeadergroupTotalAnalysisMapper leadergroupTotalAnalysisMapper;
@Override
protected void setParameters(Map parameters) {
super.parameters = parameters;
}
@Override
protected List> ListXYAxis() {
return leadergroupTotalAnalysisMapper.getLeadergroupExcellentRates(parameters);
}
}
对应的javaBean对象
BarSimple
package com.huajie.entity.echarts;
import java.util.List;
import lombok.Data;
/**
* @author xiewenfeng
* echarts普通柱状图
*/
@Data
public class BarSimple {
//legend中data的数据
private List legendData;
private List xAxisData;
private List yAxisData;
private List> seriesData;
}
LineSimple
package com.huajie.entity.echarts;
import java.util.List;
import lombok.Data;
@Data
public class LineSimple {
private List xAxisData;
private List yAxisData;
private List seriesData;
}
package com.huajie.entity.echarts;
import lombok.Data;
@Data
public class ExtMapData {
private K name;
private V value;
}
最后一步,业务模板调用的代码如下:工厂创建这一块后期会处理成单例模式,在下一篇文章中说明
private EchartsFactory echartsFactory = new DefaultEchartsFactory();
@Override
public BarSimple getBarSimple(Map conditionMap) {
AbstractBarSimple createBarSimple = echartsFactory.createBarSimple(conditionMap,BarSimpleImpl.class);
return createBarSimple.initEchartsData();
}
@Override
public LineSimple getLineSimple(Map conditionMap) {
AbstractLineSimple createLineSimple = echartsFactory.createLineSimple(conditionMap,LineSimpleImpl.class);
return createLineSimple.initEchartsData();
}
实际项目效果图: