设计模式应用 策略模式
趁还有点时间, 正好天天在学设计模式, 就把现有项目的一个小功能给重构了, 利用的是策略模式..
实战
场景: Web项目, 需求是将页面查询出的列表导出至excel, 页面有两个,分别是Order订单页面及Bill发票列表页, 两个页面的字段即excel的表头有所区别, 通过这两天学习设计模式, 重构了以前的代码.
应用策略模式
因为导出excel这个动作, 在两个页面都一样, 只是导出的内容,表头啊,字段属性名有所区别, 还有个别字段的算法有所不同, 提到算法, 我就想到策略模式了.
重构步骤
1.制作策略接口, 即算法接口, 那么我能想到的, 几个方法, 定义出来, 像是初始化数据, 制作表格, 计算等等
/**
* Excel策略类
*/
public interface IExcelStrategy {
// 初始化表格数据, 比如表头, 表头对应的java属性, 数据集合
public void initCreateExcel();
// ...下面还有制作表格的方法等....
}
2.制作具体的策略实现
/**
* Excel一些通用的属性
*/
public class Excel {
protected String[] titles;
protected String[] keys;
protected List<Object> dataList;
.... get set 方法
}
/**
* Excel策略实现类
* 注意: 继承Excel实体类, 因为不同策略类之间有共同属性
*/
public class OrderExcelStrategy extends Excel implements IExcelStrategy {
private IOrderDao orderDao;
public void initCreateExcel() {
this.titles = new String[]{
"订单号","订单"
};
this.keys = new String[]{
"code","order"
};
this.dataList = waresDao.findAll();
System.out.println("order初始化完毕");
}
}
public class BillExcelStrategy extends Excel implements IExcelStrategy{
private IBillDao billDao;
public void initCreateExcel() {
this.titles = new String[]{
"发票号","发票"
};
this.keys = new String[]{
"bnumber","bill"
};
this.dataList = waresDao.findAll();
System.out.println("bill初始化完毕");
}
}
3.制作策略上下文类
public class ExcelContext {
private IExcelStrategy excelStrategy;
/**
* 此处结合一下简单工厂模式
*/
public ExcelContext(int type) {
switch (type) {
case 1:
this.excelStrategy = getBean("orderExcelStrategy");
break;
case 2:
this.excelStrategy = getBean("billExcelStrategy");
break;
default:
break;
}
}
public void initCreateExcel() {
this.excelStrategy.initCreateExcel();
}
public IExcelStrategy getBean(String beanName) {
return (IExcelStrategy) ApplicationUtil.getBean(beanName);
}
}
switch在这里不直接new OrderExcelStrategy()的原因:
因为new对象的话, OrderExcelStrategy对象里的orderDao属性, 就会为null, 原因是spring只有在项目加载时,注入了orderDao这个bean, 新建对象自然就没有了, 想要获取这个bean可以通过下面的工具类获得. 我在这里的思路没有获得orderDao这个bean, 我是直接获得orderExcelStrategy这个bean, 其实一样的, 我预先在xml中同样配置了orderExcelStrategy这个bean.
<!-- bean 配置 -->
<bean id="orderExcelStrategy" class="com.order.excel.OrderExcelStrategy">
<property name="orderDao" ref="orderDao"/>
</bean>
<bean id="billExcelStrategy" class="com.bill.excel.BillExcelStrategy">
<property name="billDao" ref="billDao"/>
</bean>
4.控制层的调用
public ModelAndView exportExcel(HttpServletRequest request, HttpServletResponse response) {
// 区分 发票 还是 订单
String type = request.getParameter("type");
// 导出功能处理...
new ExcelContext(Integer.parseInt(type)).initCreateExcel();
.... 其他处理
}
整个导出功能变成了一句代码, 或者是几句代码, 因为这刚刚initCreateExcel么, 还有makeExcel等等, 反正是简介没观了不少.
获取bean的工具类
在获取servce 或者 是dao 的bean的时候, 需要用到这样一个工具类
public class ApplicationUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationUtil.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
}
注意: 让该bean在xml中配置走一遍, applicationContext
属性便注入进去了.
<bean id="随便起了" class="com.excel.utils.ApplicationUtil"/>
UML图