提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
需求:现有多种类型的回单,每种回单排版不同,使用数据取值也不同,所以需要根据回单类型,生成不同类型的回单。
一、什么是策略模式?
策略模式其实也是在解耦,把策略的定义、创建、使用这三个部分解耦开来,因为本身策略模式也是基于接口编程,这样其实可以简单的理解客户端调用使用接口进行编程,可以通过工厂方法创建对应的策略模式,进而完成对应的程序功能。(定义自己百度)
二、使用步骤
1.函数式接口
所谓的函数式接口,实际上就是接口里面只能有一个抽象方法的接口。(定义自己百度)
package com.hime.aoto.common.hdpdf;
import com.hime.aoto.project.entity.BillFlowGeneral;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
/**
* @author: lijx
* @date: 2023/1/4 15:38
* @description: 创建hdpdf内容的函数式接口
*/
@FunctionalInterface
public interface HdPdfTable {
/**
* 创建电子回单内容
* 每个实现类取值设置样式区分开,解耦合,以便于后期修改回单样式,而不影响其他回单样式
*
* @param billFlowGeneralInfo 回单信息
* @param cell PdfPCell
* @param pdfTable PdfPTable
* @param printDate 打印时间
*/
void careteTable(BillFlowGeneral billFlowGeneralInfo, PdfPCell cell, PdfPTable pdfTable, String printDate);
}
2.自定义注解
代码如下:
package com.hime.aoto.common.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* @author: lijx
* @date: 2022/10/10 9:53
* @description: 回单类型注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface BillHandlerType {
/**
* 回单类型,与数据库中 bill_flow_general的bill_format字段保持一致
*
* @return
*/
String source();
}
3.回单类型选择策略
代码中使用了Lambda表达式,仔细看应该不难懂
package com.hime.aoto.framework;
import com.hime.aoto.common.annotation.BillHandlerType;
import com.hime.aoto.common.hdpdf.HdPdfTable;
import com.hime.aoto.common.hdpdf.impl.BillAllRmfImpl;
import com.hime.aoto.common.hdpdf.impl.BillFeeRmfImpl;
import com.hime.aoto.project.entity.BillFlowGeneral;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: lijx
* @date: 2023/1/4 16:19
* @description: 回单类型生成策略
*/
@Component
public class HdPdfTableFactory {
private Map<String, HdPdfTable> hdPdfTableMap;
/**
* 通过注解@BillHandlerType和Map实现策略模式
*
* @param hdPdfTableList
*/
@Autowired
public void setHdPdfTableMap(List<HdPdfTable> hdPdfTableList) {
hdPdfTableMap = hdPdfTableList.stream().collect(
Collectors.toMap(hdPdfTable -> AnnotationUtils.findAnnotation(hdPdfTable.getClass(), BillHandlerType.class).source(),
v -> v, (v1, v2) -> v1));
}
/**
* 选择策略
*
* @param billType 回单类型
* @param billFlowGeneralInfo
* @param cell
* @param pdfTable
* @param printDate 打印时间
*/
public void getHdPdfTable(String billType, BillFlowGeneral billFlowGeneralInfo, PdfPCell cell, PdfPTable pdfTable, String printDate){
HdPdfTable hdPdfTable = hdPdfTableMap.get(billType);
if(hdPdfTable != null){
hdPdfTable.careteTable(billFlowGeneralInfo, cell, pdfTable, printDate);
}
}
}
4.接口实现类
根据不同的回单类型,编写不同的实现类,编码者不再关注怎么选择回单类型,只需编写不同类型的回单生成逻辑即可。 每个实现类只需要加上@BillHandlerType(source = “回单类型”)即可。
1)billall_rmf类型的回单
package com.hime.aoto.common.hdpdf.impl;
import com.hime.aoto.common.CreateModelNineType;
import com.hime.aoto.common.annotation.BillHandlerType;
import com.hime.aoto.common.hdpdf.HdPdfTable;
import com.hime.aoto.common.utils.DateUtils;
import com.hime.aoto.common.utils.PubUtil;
import com.hime.aoto.project.entity.BillFlowGeneral;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import org.springframework.stereotype.Service;
import static com.hime.aoto.common.CreateModelNineType.setCellMsgRowHead;
/**
* @author: lijx
* @date: 2023/1/4 15:44
* @description: 最简类回单 billall_rmf
*/
@BillHandlerType(source = "billall_rmf")
public class BillAllRmfImpl implements HdPdfTable {
@Override
public void careteTable(BillFlowGeneral billFlowGeneralInfo, PdfPCell cell, PdfPTable pdfTable, String printDate) {
//TODO something
}
}
2)billfee_rmf类型的回单
package com.hime.aoto.common.hdpdf.impl;
import com.hime.aoto.common.CreateModelNineType;
import com.hime.aoto.common.annotation.BillHandlerType;
import com.hime.aoto.common.hdpdf.HdPdfTable;
import com.hime.aoto.common.utils.DateUtils;
import com.hime.aoto.common.utils.PubUtil;
import com.hime.aoto.project.entity.BillFlowGeneral;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
/**
* @author: lijx
* @date: 2023/1/5 10:13
* @description: 2)电子回单箱扣费回单 billfee_rmf
*/
@BillHandlerType(source = "billfee_rmf")
public class BillFeeRmfImpl implements HdPdfTable {
@Override
public void careteTable(BillFlowGeneral billFlowGeneralInfo, PdfPCell cell, PdfPTable pdfTable, String printDate) {
//TODO something
}
}
3)更多实现类…
4.方法调用
== 如果使用if else,每次增加还需要处理条件分支语句,而使用策略模式,每增加一种类型的回单,只需要新增一个实现类,不用修改其他任何代码。==
SpringUtils.getBean(HdPdfTableFactory.class).getHdPdfTable(bill_format, billFlowGeneralInfo, cell, titleTable, printDateTime);
总结
策略模式的优点:
1、干掉繁琐的 if、switch 判断逻辑;
2、代码优雅、可复用、可读性好;
3、符合开闭原则,扩展性好、便于维护;
策略模式的缺点:
1、策略如果很多的话,会造成策略类膨胀;
2、使用者必须清楚所有的策略类及其用途;