茶余饭后的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
小结
以上就是策略模式实现方式,简单来说,可以理解为将多变的方法抽离出来,进行解耦合。