java编程/提升

手把手教你用策略模式 写echarts的配置项option

2020-08-17  本文已影响0人  程序员ken

前言:策略模式和适配器模式很像 但前者策略的接口和相关类会暴露出来,并且每个策略的“计算内容”都不同【常用于计算】。

一、研究下echarts官网的重要配置

1.1 常用项主要有title legend xAxis yAxis legend dataset series textStyle 如下图所示

file
file

二、建立Echarts的option类 我在此命名为EchartsOption 【注:后面一般option下直接属性 java命名前缀都是Echarts】

package com.ken.sys.common.entity.echarts.option;

import com.ken.sys.common.entity.echarts.axis.EchartsXYAxis;
import com.ken.sys.common.entity.echarts.dataset.EchartDataset;
import com.ken.sys.common.entity.echarts.legend.EchartsLegend;
import com.ken.sys.common.entity.echarts.series.EchartBaseSeries;
import com.ken.sys.common.entity.echarts.textStyle.EchartsTextStyle;
import com.ken.sys.common.entity.echarts.title.EchartsTitle;

import java.util.List;

/**

}
2.1 以title 为例子 写相关 的java类EchartsTitle


file

/******************************************************************************


*****************************************************************************/
package com.ken.sys.common.entity.echarts.title;

/**

//省略get set方法

}

file

其他相关类在此不做赘述

这里简单说一下 series 使用基类【EchartBaseSeries】 其他如饼图 折线图等的series都是集成EchartBaseSeries


file

三、编写策略类【策略模式】

3.1 主要分为三部分,一是策略接口 【EchartsStrategy】 二是策略的上下文 对外暴露 匹配不同的策略 行使不同的方案

三是工厂类将策略注入 做到匹配不同的类型的策略

3.1.1 策略接口 【EchartsStrategy】

public interface EchartsStrategy {
// //创建option
<T> EchartsOption createOption(IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto);

//会创建多个option
<T>List<EchartsOption> createMulOption(IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto);

}
3.1.2 策略上下文 【EchartStrategyContext】

package com.ken.sys.common.strategycontext.echarts;

import com.ken.sys.common.entity.echarts.dto.HandEchartsDto;
import com.ken.sys.common.entity.echarts.option.EchartsOption;
import com.ken.sys.common.ifs.IEchartSeries;
import com.ken.sys.common.strategy.echarts.base.EchartsStrategy;

import java.util.List;

/**

public <T>EchartsOption createOption(IEchartSeries iEchartSeries, List<T> list,HandEchartsDto echartsDto){
    if (echartsStrategy != null) {
       return echartsStrategy.createOption(iEchartSeries,list,echartsDto);
    }
    return null;
}

//会创建多个option
public <T> List<EchartsOption> createMulOption(IEchartSeries iEchartSeries, List<T> list,HandEchartsDto echartsDto){
    if (echartsStrategy != null) {
        return echartsStrategy.createMulOption(iEchartSeries,list,echartsDto);
    }
    return null;
}


public EchartStrategyContext(EchartsStrategy echartsStrategy) {
    this.echartsStrategy = echartsStrategy;
}

private EchartStrategyContext() {
}

}
3.1.3 策略的 工厂类【EchartsStrategyFactory】

/******************************************************************************


*****************************************************************************/
package com.ken.sys.common.factory.echarts;
import com.ken.sys.common.constant.EchartsConstant;
import com.ken.sys.common.strategy.echarts.;
import com.ken.sys.common.strategy.echarts.base.EchartsStrategy;
import java.util.HashMap;
import java.util.Map;
/
*

BaseStrategy的相关方法
package com.ken.sys.common.strategy.echarts.base;

import com.ken.sys.common.entity.echarts.axis.EchartsXYAxis;
import com.ken.sys.common.entity.echarts.dto.HandEchartsDto;
import com.ken.sys.common.entity.echarts.legend.EchartsLegend;
import com.ken.sys.common.entity.echarts.option.EchartsOption;
import com.ken.sys.common.entity.echarts.series.EchartBaseSeries;
import com.ken.sys.common.entity.echarts.series.HeatMapSeries;
import com.ken.sys.common.entity.echarts.series.data.SeriesData;
import com.ken.sys.common.entity.echarts.series.property.SeriesAreaStyle;
import com.ken.sys.common.entity.echarts.series.property.SeriesItemStyle;
import com.ken.sys.common.entity.echarts.series.property.SeriesLabel;
import com.ken.sys.common.entity.echarts.series.property.SeriesLineStyle;
import com.ken.sys.common.entity.echarts.title.EchartsTitle;
import com.ken.sys.common.ifs.IEchartSeries;
import com.ken.sys.common.util.EmptyUtils;
import com.ken.sys.common.util.ReflectUtils;

import java.util.*;

/**

/**
 * 功能描述:  创建热力图的option
 * @param iEchartSeries 接口
 * @param t  对象
//     * @param titleFieldName
//     * @param subFieldName 对象里面需要处理的list数据
//     * @param xDimension 维度x轴
//     * @param yDimension 维度y
//     * @param xAxisDataName x轴需要展示的信息
//     * @param yAxisDataName y轴需要展示的信息
//     * @param showValField 需要展示数据的列
 * @return: java.util.Map<java.lang.String,java.lang.Object>
 * @author: swc
 * @date: 2020/7/2 0002 下午 12:52
 */
public static <T> EchartsOption createHeatMapOption(IEchartSeries iEchartSeries, T t, HandEchartsDto handEchartsDto) {
    EchartsOption option =new EchartsOption();
    List<EchartBaseSeries> seriesList =new ArrayList<EchartBaseSeries>();

    String titleFieldName = handEchartsDto.getTitleFieldName();

    String subFieldName = handEchartsDto.getSubFieldName();

    String xDimension = handEchartsDto.getxDimension();

    String yDimension =  handEchartsDto.getyDimension();

    String xAxisDataName = handEchartsDto.getxAxisDataName();

    String yAxisDataName =  handEchartsDto.getyAxisDataName();

    String showValField =  handEchartsDto.getShowValField();

    String showDateField =  handEchartsDto.getShowDateField();

    String coordinateSystem =  handEchartsDto.getCoordinateSystem();

    Map<String,Object> map =new HashMap<String,Object>();


    //标题
    String titleName =null;
    if(!EmptyUtils.isNullOrEmpty(titleFieldName)){
        titleName =  ReflectUtils.getFieldValue(t,titleFieldName).toString();
    }

    List subList  = (List)ReflectUtils.getFieldValue(t,subFieldName);

    Set<String> xAxisData =new TreeSet<String>();

    Set<String> yAxisData =new TreeSet<String>();

    //数据值---单个数据
    List seriesDataValue ;

    EchartBaseSeries echartBaseSeries = new HeatMapSeries();

    if("calendar".equals(coordinateSystem)){
        ((HeatMapSeries)echartBaseSeries).setCoordinateSystem("calendar");
        ((HeatMapSeries)echartBaseSeries).setCalendarIndex(handEchartsDto.getCalendarIndex());
    }


    List<SeriesData> seriesDataList = new ArrayList<SeriesData>();
    SeriesData seriesData =null;

    String xAxisValue =null;
    String yAxisValue =null;
    // 维度X
    String xDim = null;
    // 维度y
    String yDim = null;
    for(int i=0;i<subList.size();i++){
        seriesData =new SeriesData();

        if(!EmptyUtils.isNullOrEmpty(xDimension)){
            // 维度X
            xDim =  ReflectUtils.getFieldValue(subList.get(i),xDimension).toString();
        }

        if(!EmptyUtils.isNullOrEmpty(xDimension)){
            // 维度y
            yDim =  ReflectUtils.getFieldValue(subList.get(i),yDimension).toString();
        }


        //x轴的值
        if(!EmptyUtils.isNullOrEmpty(xAxisDataName)){
            xAxisValue =  ReflectUtils.getFieldValue(subList.get(i),xAxisDataName).toString();
            xAxisData.add(xAxisValue);
        }

        //y轴的值
        if(!EmptyUtils.isNullOrEmpty(yAxisDataName)){
            yAxisValue =  ReflectUtils.getFieldValue(subList.get(i),yAxisDataName).toString();
            yAxisData.add(yAxisValue);
        }

        seriesDataValue =new ArrayList();

        //目前支持cartesian2d出现x-y维度
        if("cartesian2d".equals(coordinateSystem)){
            seriesDataValue.add(xDim);
            seriesDataValue.add(yDim);
        }

        //coordinateSystem为calendar series里面的data-[value]为时间+某项值的数组
        if("calendar".equals(coordinateSystem)){
            Object showDate =EmptyUtils.isNullOrEmpty(showDateField)?0:ReflectUtils.getFieldValue(subList.get(i),showDateField);
            seriesDataValue.add(showDate);
        }


        Object showVal =EmptyUtils.isNullOrEmpty(showValField)?0:ReflectUtils.getFieldValue(subList.get(i),showValField);
        seriesDataValue.add(showVal);

        seriesDataValue.add(subList.get(i));

        //设置值
        seriesData.setValue(seriesDataValue);

// seriesData.setVisualMap(false);

        if(!EmptyUtils.isNullOrEmpty(iEchartSeries)){
            iEchartSeries.setSeriesDetailProp(echartBaseSeries,new SeriesLabel(),new SeriesItemStyle(),new SeriesAreaStyle(),new SeriesLineStyle());
            iEchartSeries.setSeriesDataProp(seriesData,new SeriesLabel(),new SeriesItemStyle(),new SeriesAreaStyle(),new SeriesLineStyle());
        }

        seriesDataList.add(seriesData);
        echartBaseSeries.setData(seriesDataList);
    }

    seriesList.add(echartBaseSeries);
    EchartsTitle title =new EchartsTitle();
    title.setText(titleName);

    EchartsXYAxis xAxis =new EchartsXYAxis();
    xAxis.setData(new ArrayList(xAxisData));
    option.setxAxis(xAxis);

    EchartsXYAxis yAxis =new EchartsXYAxis();
    yAxis.setData(new ArrayList(yAxisData));
    option.setyAxis(yAxis);

    option.setSeries(seriesList);

    return option;
}


/**
 * 功能描述:
 * @param iEchartSeries 接口
 * @param list 对象
//     * @param titleFieldName
//     * @param subFieldName 对象里面需要处理的list数据
//     * @param xDimension 维度x轴
//     * @param yDimension 维度y
//     * @param xAxisDataName x轴需要展示的信息
//     * @param yAxisDataName y轴需要展示的信息
//     * @param showValField 需要展示数据的列
 * @return: java.util.Map<java.lang.String,java.lang.Object>
 * @author: swc
 * @date: 2020/7/2 0002 下午 12:52
 */
public static <T> List<EchartsOption> createHeatMapOption(IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto) {
    List<EchartsOption> optionList =new ArrayList<EchartsOption>();
    String coordinateSystem =  handEchartsDto.getCoordinateSystem();

    //拼接不同年份日历的series的值
    List<EchartBaseSeries> seriesList =new ArrayList<EchartBaseSeries>();
    EchartsOption option = null;


    for(int i=0;i<list.size();i++){
        handEchartsDto.setCalendarIndex(i);
        //如果coordinateSystem 是 cartesian2d  默认为 多个[option]热力图
        if("cartesian2d".equalsIgnoreCase(coordinateSystem)){
            optionList.add(createHeatMapOption(iEchartSeries,list.get(i),handEchartsDto));
        }
        //如果coordinateSystem 是 calendar  默认为 日历 则是一个option的热力图  series的值为多个 而不是一个
        if("calendar".equalsIgnoreCase(coordinateSystem)){
            option = createHeatMapOption(iEchartSeries, list.get(i), handEchartsDto);
            seriesList.addAll(option.getSeries());
        }
    }

    if("calendar".equalsIgnoreCase(coordinateSystem)){
        option.setSeries(seriesList);
        optionList.add(option);
    }

    return optionList;
}





//公告的设置多个series的方法
private void commonSetSeries(IEchartSeries iEchartSeries, Class<? extends EchartBaseSeries> seriesClass, Object[] legends, Object[] fields, List<EchartBaseSeries> mulseries, List[] saveList) throws InstantiationException, IllegalAccessException {
    EchartBaseSeries echartBaseSeries;
    for (int ind = 0; ind < fields.length; ind++) {
        //获取指定的series
        echartBaseSeries = seriesClass.newInstance();
        echartBaseSeries.setName((String) legends[ind]);
        echartBaseSeries.setData(saveList[ind]);
        //设置整体样式[如一条折线或条状图的样式]
        if (!EmptyUtils.isNullOrEmpty(iEchartSeries)) {
            iEchartSeries.setSeriesDetailProp(echartBaseSeries, new SeriesLabel(), new SeriesItemStyle(), new SeriesAreaStyle(), new SeriesLineStyle());
        }
        mulseries.add(echartBaseSeries);
    }
}

}
五、为了方便 最后写了工具类【EChartsNewUtil】 把策略调用进行封装

注:1.这里主要看有注释的方法 因为参数是最全的 2.关于IEchartSeries ,EchartsStrategy 这两类,IEchartSeries 是针对series的数据处理 或添加修改样式(毕竟每个公司 /每个系统业务多多少少会有些不同) ,EchartsStrategy 这个是自定义你自己业务需求的策略(需要继承EchartsStrategy ,这个完全是重新定义这个方法 IEchartSeries 再次不起作用 除非你自动代码回调到它)

5.1 HandEchartsDto是封装的参数,用于反射数据源的属性或处理部分业务

/******************************************************************************


*****************************************************************************/
package com.ken.sys.common.entity.echarts.dto;
import java.util.List;
/**

}
package com.ken.sys.common.util;
import com.ken.sys.common.entity.echarts.dto.HandEchartsDto;
import com.ken.sys.common.entity.echarts.option.EchartsOption;
import com.ken.sys.common.factory.echarts.EchartsStrategyFactory;
import com.ken.sys.common.ifs.IEchartSeries;
import com.ken.sys.common.strategy.echarts.base.EchartsStrategy;
import com.ken.sys.common.strategycontext.echarts.EchartStrategyContext;

import java.util.*;

public class EChartsNewUtil {

/**
 * 功能描述: 
 * @param type 图形类别
 * @param iEchartSeries 外部接口 用于重写参数 或 样式等
 * @param list  数据源
 * @param handEchartsDto  需要处理的相应字段【list或list的子集里面】
 * @return: com.ken.sys.common.entity.echarts.option.EchartsOption
 * @param strategy  自定义的策略
 * @author: swc
 * @date: 2020/7/4 0:48
*/ 
public static <T>EchartsOption creatOption(String type, IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto, EchartsStrategy strategy) {
    //获取匹配的策略
    if(EmptyUtils.isNullOrEmpty(strategy)){
        strategy =EchartsStrategyFactory.getEchartsStrategy(type);
    }
    EchartStrategyContext context = new EchartStrategyContext(strategy);
    return context.createOption(iEchartSeries,list,handEchartsDto);
}

public static <T>EchartsOption creatOption(String type, List<T> list, HandEchartsDto handEchartsDto) {
    return creatOption(type,null,list,handEchartsDto,null);
}

public static <T>EchartsOption creatOption(String type, List<T> list, HandEchartsDto handEchartsDto,EchartsStrategy strategy) {
    return creatOption(type,null,list,handEchartsDto,strategy);
}

public static <T>EchartsOption creatOption(String type,IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto) {
    return creatOption(type,iEchartSeries,list,handEchartsDto,null);
}

/**
 * 功能描述:
 * @param type 图形类别
 * @param iEchartSeries 外部接口 用于重写参数 或 样式等
 * @param list  数据源
 * @param handEchartsDto  需要处理的相应字段【list或list的子集里面】
 * @param strategy  自定义的策略
 * @return: com.ken.sys.common.entity.echarts.option.EchartsOption
 * @author: swc
 * @date: 2020/7/4 0:48
 */
public static <T>List<EchartsOption> creatMulOptionForHeatMap(String type, IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto,EchartsStrategy strategy) {
    //获取匹配的策略
    if(EmptyUtils.isNullOrEmpty(strategy)){
        strategy =EchartsStrategyFactory.getEchartsStrategy(type);
    }
    EchartStrategyContext context = new EchartStrategyContext(strategy);
    return context.createMulOption(iEchartSeries,list,handEchartsDto);
}

public static <T>List<EchartsOption> creatMulOptionForHeatMap(String type, IEchartSeries iEchartSeries, List<T> list, HandEchartsDto handEchartsDto) {
    return creatMulOptionForHeatMap(type,iEchartSeries,list,handEchartsDto,null);
}


public static <T>List<EchartsOption> creatMulOptionForHeatMap(String type, List<T> list, HandEchartsDto handEchartsDto, EchartsStrategy strategy) {
    return creatMulOptionForHeatMap(type,null,list,handEchartsDto,strategy);
}

public static <T>List<EchartsOption> creatMulOptionForHeatMap(String type, List<T> list, HandEchartsDto handEchartsDto) {
    return creatMulOptionForHeatMap(type,null,list,handEchartsDto,null);
}

}

六、测试数据和测试该工具类

部分代码

//柱状图 折线图
@Test
public void barOrLine()throws Exception{
    String type=EChartsUtil.LINE;//BAR
    List<EchartsEntity> list= getData();

    Object[] legends ={"总金额","实付金额"};
    Object[] fields ={"nums1","nums2"};

    List[] saveList =new List[]{new ArrayList<BigDecimal>(),new ArrayList<BigDecimal>()};

    HandEchartsDto dto =new HandEchartsDto();

    dto.setxAxisDataName("name");
    dto.setLegends(legends);
    dto.setFields(fields);
    dto.setSaveList(saveList);

    EchartsOption option = EChartsNewUtil.creatOption(type, new IEchartSeries() {
        @Override
        public void setSeriesDetailProp(EchartBaseSeries series, SeriesLabel label, SeriesItemStyle itemStyle, SeriesAreaStyle areaStyle, SeriesLineStyle lineStyle) {

// ((BarSeries) series).setBarMaxWidth("60%");
// label.setShow(true);
// label.setPosition("top");
// series.setLabel(label);
}

        @Override
        public void setSeriesDataProp(SeriesData seriesData, SeriesLabel label, SeriesItemStyle itemStyle, SeriesAreaStyle areaStyle, SeriesLineStyle lineStyle) {

        }
    }, list, dto);
    option.setSeries(null);
 
}

源码:https://gitee.com/ten-ken/java-wheel/tree/master/ken [先找测试类TestStrategyEcharts]

微信: tianji_vip

file

本文来源于:宋文超super,专属平台有csdn、思否(SegmentFault)、 简书、 开源中国(oschina),转载请注明出处。

上一篇 下一篇

猜你喜欢

热点阅读