【“别跟我不会”系列】Java设计模式之策略模式
- 2019 年 10 月 8 日
- 笔记
茶余饭后的IT小知识,不说了,都是干货。 —— 23号老板
0
1
引入
原创:爱吃回锅肉的瘦子
一直以来,笔主想写关于设计模式的系列文章与大家进行交流,但碍于自己经验上尚浅,无法将此讲解透彻,闹了笑话。但千里之行,始于足下,我决定将我自己的工作中我用到的设计模式与大家分享交流,有不妥还望大家指出。
设计模式一种设计开发上的经验总结,既然是经验上的总结,那么实践是必然的;但他又是一种设计,所以在我们对需求必须得非常了解,对他可能以后出现什么样的变化有个预测。此次我打算先从设计模式中的策略模式讲起。
0
2
概念
在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
代码上的设计上大体架构:
1、抽象的行为:
public interface Behavior { public void toDo(); }
2、实现抽象行为的两个类
public class OneBehavior implements Behavior{ @Override public void toDo() { System.out.println("one"); } }
public class TwoBehavior implements Behavior { @Override public void toDo() { System.out.println("two"); } }
3、定义公有的行为类:
public class DataBase { protected Behavior behavior; public DataBase(Behavior behavior) { this.behavior = behavior; }
public void query(){ behavior.toDo(); }
public void delete(){ System.out.println("delete"); } }
从上面代码架构上看,可以看到策略模式的方式本身就是将本身属于database中的某些方法抽离出来,用接口的方式来抽象方法。既然这样,那与我们常用的模板模式有什么区别呢?
为何不将database设计成抽象类,然后将此进行各个子类实现,我们也可以做到不同方法的实现。注意设计模式是结合具体场景而使用的一种经验模式。
0
3
深入
那么在什么样的场景下使用策略模式,有什么样的场景下使用模板模式呢?
我们知道,在对代码评价有个复用性比较,那么我们可以假设这样的一个场景:
假设在query方法中 我们目前只有两种的查询逻辑方式,但是有9个查询需要使用,其中有6个是使用相同的query()。这样的话,在使用模板模式中我们对query()方法要写6个相同的代码。的确,我们还可以将这6个中再写一个父类继承,此父类再继承database,但是delete方法中在这6个有三个delete相同呢又或者其中三个delete方法又与前面3个子类相同呢?
这时候我们用模板模式来实现不同的方法是不可行的。必须将方法解耦化,如何解耦呢?将变化的方法抽象成接口,将database依赖于该接口,也就是说我们可以将接口作为属性给予database。综上,在笔主看来,策略模式就是将一些多变的方法抽象出来,来增加代码的复用。
注意点:
1、分析项目中的变化部分与不变部分;
2、多用组合少用继承;用行为类组合,而不是行为的继承,更有弹性;
0
4
实战部分
笔主是主要开发报表功能的,难免牵扯到生成excel。我这边生成excel有三种方式,poi,easyExcel,以及第三方软件。他们各个使用方式有不同的划分。如果想了解Excel是如何使用poi解析的可以看看前面的文章。(如果找不见,可加微信bboyHan索要)
那么我那时候为啥选择使用策略模式,是基于什么样的考量呢?这里就开始讨论方法论了。刚开始的时候 ,获取Excel不是那么复杂, 我只是单纯的使用POI方式生成excel,后面由于有性能上要求,就使用上了easyExcel,在后来excel表格复杂化了,为了便于维护就使用上了第三方软件功能,再后来运营还要求导出pdf。当然了,这些是需求在讨论时候就已经确认要分多次迭代了。如果是三张报表,分别用这三个获取excel方式,那简单使用mvc模型就差不多解决了。但是笔主面对的是几百张报表,必须得将此抽离出来所有的导出功能。也就是我设计一个接口 getFile(),三个行为类poi、easyExcel、第三方实现getFile();再写一个参数基本类,将选择什么样方式导出放在此处,然后在写一个获取数据获取类,并依赖getFile类。代码如下:
public interface GetFile { public File toDo(); }
public class PoiFile implements GetFile { @Override public File toDo() { System.out.println("poi"); return new File("poi"); } }
public class EasyExcelFile implements GetFile { @Override public File toDo() { System.out.println("EasyExcel"); return new File("EasyExcel"); } }
public class DataBase { protected GetFile getFile; public DataBase(GetFile behavior) { this.getFile = behavior; } public void query(){ getFile.toDo(); } public void delete(){ System.out.println("delete"); } }
public class TwoData extends DataBase { public TwoData(GetFile file) { super(file); } @Override public void query() { this.getFile.toDo(); } }
public class OneData extends DataBase{ public OneData(GetFile getFile) { super(getFile); } @Override public void query() { this.getFile.toDo(); } }
参数类:
public class RequestModel implements Serializable { private String type; public GetFile getFile(){ if("POI".equalsIgnoreCase(getType()))return new PoiFile(); else return new EasyExcelFile(); } public String getType() { return type; }
public void setType(String type) { this.type = type; }
}
service层:
//交给sring管理DataBase dataBase; public void query(RequestModel rq){ dataBase.query(); }
0
5
小结
以上就是策略模式实现方式,简单来说,可以理解为将多变的方法抽离出来,进行解耦合。