echarts后台接口编写思路及装饰者模式的应用

若您想了解装饰者模式,劳烦您跳转谈一下自己对装饰者模式的理解

背景

最近公司需要做一个报表展示页,采用前后分离的方式去编写,而我需要的是给前端返回echarts所需要的数据。

由于echarts后台整体编写代码较多,在这里主要给大家提供个思路,而且这篇的主要目的是想加深对上篇装饰者模式的理解,所以恳请大家多多包涵。

思路

以此图为例(相对来说具有代表性):
在这里插入图片描述

我们可以很清楚的知道我们要返回的数据全在option所以在此可以将他的重要类型封装到模型model一并返回:

  1. option必要属性为legend料,面,xAxis,yAxis以及series,前端所需要的数据全在这些属性内
  2. 上面类是碗及的4个重要属性里面内部又包含‘name’,‘data’,'type’这些元素,所以也需要将以上4个属性进行二次封装,属性为以上3个元素;
  3. 运用建造者模式,提取公共方法(返回sql数据),比如图的类型,图例数据,获取x,y坐标等等的…将各自的数据统一封装到各自的类里面;
  4. 在以上的基础上运用策略+工厂模式进行图的区分,比如有些仪表盘,饼图,柱状图等,(因为这些图内部的参数不一样,难点在series),调度属于哪一个图的所属方法进行数据赋值并返回;

转换成图形解释就是这样的:
在这里插入图片描述
可能说的有些些许的抽象,改天如果有时间我还是详细写一篇吧…

插曲

我还是说一下为什么要以echarts的series模型为例吧。

是这样的,由于series的属性太多,而主要的3个就是name,type和data,但是区别在于其他的属性(这里暂时以饼图里面的radius属性为例,当然也可以是其他的,比如max,min…等等):

比如部分饼图有的是同心圆,有的是实体圆,区别就在“radius: [‘50%’, ‘70%’]”这个属性;

但是我有时候就必须显示同心圆,有的时候我需要实体圆,但是如果我把radius这个属性写到主类里面去,那就代表无论我怎么实现都只能是同心圆,这就造成了代码的灵活性太差,形成死代码,无法对类进行扩展功能。

所以我想到了装饰者模式。

装饰者模式的实现(series系列拓展功能类的实现)

series主类:

​ 类似装饰者模式UML图的Concrete component角色

//series封装模型
public class EChartSeriesModel<T> implements Serializable{
    private static final long serialVersionUID = 541075107461913899L;
	protected String name;
	protected String type;
	protected List<T> data;//系列数据

	public EChartSeriesModel(String name, String type, List<T> data) {
		this.name = name;
		this.type = type;
		this.data = data;
	}
    //装饰方法,返回最后装饰model
    public EChartSeriesModel returnModel(){
		return new EChartSeriesModel(name,type,data);
	}
    getXXX/setXXX方法(必须有)
}

装饰类:

​ 类似装饰者模式UML图的Decorator角色

//装饰类
public class SeriesElementModel<T> extends EChartSeriesModel<T> implements Serializable{
	private static final long serialVersionUID = 3637639371336594864L;
	protected EChartSeriesModel<T> eChartSeriesModel;//主类model
    //装饰方法
	public EChartSeriesModel<T> decorate(EChartSeriesModel eChartSeriesModel){
		return this.eChartSeriesModel = eChartSeriesModel;
	}
    //构造方法
	public SeriesElementModel(String name, String type, List<T> data) {
		super(name, type, data);
	}

	@Override
	public EChartSeriesModel returnModel(){
		return new SeriesElementModel(name, type, data);
	}

}

装饰具体实现类:

​ 类似装饰者模式UML图的Concrete Decorator角色

public class SeriesRadiusModel<T> extends SeriesElementModel<T> implements Serializable {
    private static final long serialVersionUID = -4425829752029191482L;
	//拓展属性
    private List<String> radius = new ArrayList<>();
	//这块您看不懂是因为这块的实现原因是因为在建造者模式赋值数据使用的
    public SeriesRadiusModel(String name, String type, List<T> data, List<Map<String,String>> condition) {
        this.name = name;
        this.type = type;
        this.data = data;
        List<String> stringList = condition.stream().map(a -> a.get("radius")).collect(Collectors.toList());
        this.radius = stringList;
    }
    //重写方法
    @Override
    public EChartSeriesModel<T> returnModel(){
        SeriesRadiusModel<T> radiusModel = new SeriesRadiusModel<>();
        radiusModel.setRadius(this.radius);
        radiusModel.setName(this.name);
        radiusModel.setType(this.type);
        radiusModel.setData(this.data);
        return radiusModel;
    }
   getXXX/setXXX方法(必须写,不然获取不到radius的值)
}

实现类:

//饼图归类
public class PieGraphics implements DistinguishGraphics {

    @Override
    public <T extends ChartModel, R> EChartResponseModel transformToEchartResponseModel(List<CodeItem> legends, T t, List<Map<String, Object>> datalist, Map<String, String> legendReverseMap, EchartLegendModel strLegends, String graphics, int seriesElementModel, List<Map<String,String>> condition) {
        List<EChartPieModel> echartData = datalist.stream().map(b ->{
            return new EChartPieModel(legendReverseMap.get(t.getLegendCode(b)),t.getValueByLegends(b,legendReverseMap.get(t.getLegendCode(b))).toString());
        }).collect(Collectors.toList());
        ArrayList series = null;
        EChartSeriesModel<EChartPieModel> seriesModel = new EChartSeriesModel<>();
        switch (seriesElementModel){
            case 1://装饰者模式的应用
                SeriesRadiusModel<EChartPieModel> seriesRadiusModel = new SeriesRadiusModel("", graphics, echartData, condition);
                seriesRadiusModel.decorate(seriesModel);
                series = new ArrayList() {{ add(seriesRadiusModel.returnModel());}};
                 break;
            case 2://装饰者模式的应用
                SeriesMaximumModel<EChartPieModel> seriesMaximumModel = new SeriesMaximumModel("", graphics, echartData, condition);
                seriesMaximumModel.decorate(seriesModel);
                series = new ArrayList() {{ add(seriesMaximumModel.returnModel());}};
                break;
            default://装饰者模式的应用
                EChartSeriesModel eChartSeriesModel = new EChartSeriesModel<>("", graphics, echartData);
                series = new ArrayList() {{ add(eChartSeriesModel);}};
        }

        return new EChartResponseModel(strLegends,new ArrayList<>(),new ArrayList<>(), series);
    }

}

可能在实现类这里有点乱,我把它摘抄出来吧(如下):

			case 1:
                SeriesRadiusModel<EChartPieModel> seriesRadiusModel = new SeriesRadiusModel("", graphics, echartData, condition);
                seriesRadiusModel.decorate(seriesModel);
                series = new ArrayList() {{ add(seriesRadiusModel.returnModel());}};
                 break;
            case 2:
                SeriesMaximumModel<EChartPieModel> seriesMaximumModel = new SeriesMaximumModel("", graphics, echartData, condition);
                seriesMaximumModel.decorate(seriesModel);
                series = new ArrayList() {{ add(seriesMaximumModel.returnModel());}};
                break;
            default:
                EChartSeriesModel eChartSeriesModel = new EChartSeriesModel<>("", graphics, echartData);
                series = new ArrayList() {{ add(eChartSeriesModel);}};

最后的显示效果为:

在series3个主元素的基础上增加了raduis

未用装饰者模式之前:

在这里插入图片描述

用了装饰者模式之后:

在这里插入图片描述

总结

其实,自我感觉这块代码的实现还是有弊端的,就是在实现类这里,你使用的多少属性,在这里就得添加多少,对于类的开放——封闭原则多少是有侵入性的。

如您有更好的建议的话,非常感谢大佬的提议

一只努力奋斗的野生程序猿,欢迎大佬们前来技术交流~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值