项目场景:
项目场景:最近接到总监接的一个健身会所的后端开发和微信公众号小程序的需求开发。里面涉及一个设计模式使用的业务,记录下一遍后续复习。1年小白程序员。问题描述:
现在有如下一个原型图: ![原型图](https://img-blog.csdnimg.cn/716254fa0fec4fb280b8e5a15829142d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YSS6ZuF55qE5rGh5ZWm5ZWmUUFR,size_19,color_FFFFFF,t_70,g_se,x_16)具体需求是选择某天的某个场地,然后付费就可以完成场地的预定。主要是这个表格的数据结构比较复杂,代码会写一大堆。想到最近学到了构建者模式可以用一下。
前端要求的数据结构是这样的。至于为什么要这么的数据结构请参考elementui去找吧(其实我也没找到这东西哪来的)。主要也就是利用构建这模式完成这个数据结构的组件给前端。
{
"columnProperty": [
{
"label": "2021-12-01",
"property": "data0",
"status": 0,
"value": null,
"week": "星期三"
},
{
"label": "2021-12-02",
"property": "data1",
"status": 0,
"value": null,
"week": "星期四"
},
{
"label": "2021-12-03",
"property": "data2",
"status": 0,
"value": null,
"week": "星期五"
},
{
"label": "2021-12-04",
"property": "data3",
"status": 1,
"value": null,
"week": "星期六"
},
{
"label": "2021-12-05",
"property": "data4",
"status": 1,
"value": null,
"week": "星期日"
},
{
"label": "2021-12-06",
"property": "data5",
"status": 0,
"value": null,
"week": "星期一"
},
{
"label": "2021-12-07",
"property": "data6",
"status": 0,
"value": null,
"week": "星期二"
},
{
"label": "2021-12-08",
"property": "data7",
"status": 0,
"value": null,
"week": "星期三"
},
{
"label": "2021-12-09",
"property": "data8",
"status": 0,
"value": null,
"week": "星期四"
},
{
"label": "2021-12-10",
"property": "data9",
"status": 0,
"value": null,
"week": "星期五"
}
],
"label": "篮球场",
"price": 20,
"tableData": [
{
"id": 0,
"timeslot": "06:00-07:00",
"data0": 1,
"data1": 0,
"data2": 0,
"data3": 0,
"data4": 0,
"data5": 0,
"data6": 0,
"data7": 0,
"data8": 0,
"data9": 0
},
{
"id": 1,
"timeslot": "07:00-08:00",
"data0": 0,
"data1": 0,
"data2": 0,
"data3": 0,
"data4": 0,
"data5": 0,
"data6": 0,
"data7": 0,
"data8": 0,
"data9": 0
},
{
"id": 2,
"timeslot": "08:00-09:00",
"data0": 0,
"data1": 0,
"data2": 0,
"data3": 0,
"data4": 0,
"data5": 0,
"data6": 0,
"data7": 0,
"data8": 0,
"data9": 0
},
{
"id": 3,
"timeslot": "09:00-10:00",
"data0": 0,
"data1": 0,
"data2": 0,
"data3": 0,
"data4": 0,
"data5": 0,
"data6": 0,
"data7": 0,
"data8": 0,
"data9": 0
},
{
"id": 4,
"timeslot": "10:00-11:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 5,
"timeslot": "11:00-12:00",
"data0": 0,
"data1": 0,
"data2": 0,
"data3": 0,
"data4": 0,
"data5": 0,
"data6": 0,
"data7": 0,
"data8": 0,
"data9": 0
},
{
"id": 6,
"timeslot": "12:00-13:00",
"data0": 0,
"data1": 0,
"data2": 0,
"data3": 0,
"data4": 0,
"data5": 0,
"data6": 0,
"data7": 0,
"data8": 0,
"data9": 0
},
{
"id": 7,
"timeslot": "13:00-14:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 8,
"timeslot": "14:00-15:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 9,
"timeslot": "15:00-16:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 10,
"timeslot": "16:00-17:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 11,
"timeslot": "17:00-18:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 12,
"timeslot": "18:00-19:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 13,
"timeslot": "19:00-20:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 14,
"timeslot": "20:00-21:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
},
{
"id": 15,
"timeslot": "21:00-22:00",
"data0": 2,
"data1": 2,
"data2": 2,
"data3": 2,
"data4": 2,
"data5": 2,
"data6": 2,
"data7": 2,
"data8": 2,
"data9": 2
}
]
}
解决方案:
构建者模式具体我就不描述了,可以去百度上参考相关的博文或去b战看视频。
首先看下数据库设计:
基础场地维护表,场地构建的逻辑就是根据这个表来的。
场地设计,就是每一个时间段需要的字段,本质上也就是构建出一个二维数组。
时间段表,这个后面可以维护到数据字典中。
具体数据如下:
直接上代码了
首先是具体的构建产品,这是构建者模式的核心角色之一:
具体产品
package com.jlht.venue.api.to;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* @Author LiYong
* @Date 2021年12月01日 10:53
* @Description 构建者模式创建对象,当前角色产品角色
**/
@Data
public class VenueTableTo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 场地x轴信息
*/
private List<ColumnProperty> columnProperty;
/**
* 场地名称
*/
private String label;
/**
* 场地价格
*/
private BigDecimal price;
/**
* 场地y轴
*/
private List<Map<String,Object>> tableData;
}
抽象构建者角色
package com.jlht.venue.provider.builder;
import com.jlht.venue.api.to.ColumnProperty;
import com.jlht.venue.api.to.VenueTableTo;
import java.math.BigDecimal;
import java.util.List;
/**
* @Author LiYong
* @Date 2021年12月01日 11:34
* @Description 构建者模式创建对象, 当前角色是抽象构建者
**/
public abstract class AbsTableBuilder {
//组合具体产品对象
protected VenueTableTo venueTableTo = new VenueTableTo();
//抽象构建复杂对象ColumnProperty
public abstract void buildColumnProperty();
//抽象构建复杂对象TableData
public abstract void buildTableData();
//抽象构造label
public abstract void buildLabel();
//抽象构造price
public abstract void buildPrice();
//返回具体对象
public VenueTableTo getVenueTableTo() {
return venueTableTo;
}
}
具体构建者对象
package com.jlht.venue.provider.builder.concrete;
import cn.hutool.core.date.Week;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jlht.common.utils.DateUtils;
import com.jlht.venue.api.entity.BaseVenueEntity;
import com.jlht.venue.api.entity.VenueShowEntity;
import com.jlht.venue.api.entity.VenueTimeslotEntity;
import com.jlht.venue.api.service.IBaseVenueService;
import com.jlht.venue.api.service.IVenueShowService;
import com.jlht.venue.api.service.IVenueTimeslotService;
import com.jlht.venue.api.to.ColumnProperty;
import com.jlht.venue.provider.builder.AbsTableBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author LiYong
* @Date 2021年12月01日 11:39
* @Description 构建者模式创建对象, 当前角色是具体构建者
**/
@Component
public class VenueTableBuilder extends AbsTableBuilder {
@Autowired
private IVenueShowService venueShowService;
@Autowired
private IBaseVenueService baseVenueService;
@Autowired
private IVenueTimeslotService venueTimeslotService;
private String venueId;
public void setVenueId(String venueId) {
this.venueId = venueId;
}
@Override
public void buildColumnProperty() {
//获取当前所有的时间
List<String> dateStrList =venueShowService.venueDateList(venueId);
//组装VenueTable数据
List<ColumnProperty> columnProperties = new ArrayList<>();
for (int i = 0; i < dateStrList.size(); i++) {
ColumnProperty columnProperty = new ColumnProperty();
String date = dateStrList.get(i);
columnProperty.setLabel(date);
columnProperty.setProperty("data" + i);
//判断时期是否是周末,0不是,1是
Week week = DateUtils.getWeek(date);
columnProperty.setStatus(week.getValue() == 1 || week.getValue() == 7 ? 1 : 0);//这里不符合开发规范
columnProperty.setValue(null);
//获取当前日期是周几
String weekStr = week.toChinese();
columnProperty.setWeek(weekStr);
columnProperties.add(columnProperty);
}
venueTableTo.setColumnProperty(columnProperties);
}
@Override
public void buildTableData() {
List<Map<String,Object>> maps = new ArrayList<>();
List<VenueTimeslotEntity> timeslotList = venueTimeslotService.list();
//查询生成的场地信息
List<VenueShowEntity> venueShowList = venueShowService.queryByVenueId(venueId);
//获取当前所有的时间
List<String> dateStrList =venueShowService.venueDateList(venueId);
venueShowList.stream().map(item -> item.getDate()).distinct().collect(Collectors.toList());
for (int i = 0; i < timeslotList.size(); i++) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("id",i);
String timeSlot = timeslotList.get(i).getTimeSlot();
map.put("timeslot",timeSlot);
for (int j = 0; j < dateStrList.size(); j++) {
String date = dateStrList.get(j);
VenueShowEntity venueShowEntity = venueShowList.stream().filter(item -> item.getVenueId().equals(venueId)&&item.getTimeSlot().equals(timeSlot)&&item.getDate().equals(date)).findAny().orElse(null);
map.put("data"+j,venueShowEntity==null?2:venueShowEntity.getStatus());
}
maps.add(map);
}
venueTableTo.setTableData(maps);
}
@Override
public void buildLabel() {
//查询场地基础信息
BaseVenueEntity baseVenueEntity = baseVenueService.getById(venueId);
//设置名称
venueTableTo.setLabel(baseVenueEntity.getName());
}
@Override
public void buildPrice() {
//查询场地基础信息
BaseVenueEntity baseVenueEntity = baseVenueService.getById(venueId);
//设置价格
venueTableTo.setPrice(baseVenueEntity.getPrice());
}
}
具体使用
具体构建者被加载Spring容器中,直接@Autowire注入即可
``java
/**
* 生成场地表格json数据(构建者模式完成)
*/
@Override
public VenueTableTo getVenueTable(String venueId) {
venueTableBuilder.setVenueId(venueId);
venueTableBuilder.buildLabel();
venueTableBuilder.buildPrice();
venueTableBuilder.buildColumnProperty();
venueTableBuilder.buildTableData();
VenueTableTo venueTableTo = venueTableBuilder.getVenueTableTo();
return venueTableTo;
}
# 总结
主要还是要看自己业务需求,我个人角色构建者模式在查询的时候可能用的多一些,用来构建前端需要的数据结构。后面如果需要加字段,直接加字段就行,抽象构建对象直接build新的字段就行。如果有个新的功能需要类似的数据结构也可以直接重新继承抽象构建者对象即可。