【「別跟我不會」系列】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
小結
以上就是策略模式實現方式,簡單來說,可以理解為將多變的方法抽離出來,進行解耦合。