[代碼結構設計]根據(jù)不同條件使用不同實現(xiàn)類的業(yè)務代碼設計

場景

此時有一個場景首量,需要設計一個根據(jù)不同的狀態(tài)和條件采用不同的業(yè)務處理方式。

這樣大家可能不是太理解进苍。舉個例子加缘,現(xiàn)在大街小巷上的商戶都采用了聚合支付的支付方式,聚合支付也就是商戶柜臺前放了一個支持支付寶觉啊、微信拣宏、京東錢包、銀聯(lián)等等的二維碼杠人,用戶可以通過任意一款支付APP進行支付勋乾。

解決思路

思路①

對每個支付渠道進行定義枚舉類型

public enum PayWay {
    ALI_PAY,

    WECHAT_PAY;
}

然后在每個對應的service上定義注解宋下,表示對應哪種支付方式

@Pay(PayWay.ALI_PAY)
public class AliPayServiceImpl implements PayService  {}

但是仔細思考后,還是存在一些問題

  1. 如果增加一個支付方式后還需要修改辑莫,PayWay這個枚舉類型
  2. 在程序中学歧,仍需要根據(jù)不同的條件做if else判斷PayWay,增加支付方式還是得修改原有的判斷邏輯各吨。偽代碼如下
if("xxx" == "aliPay"){
    
} else if("xxx" == "wechatPay"){
    
}
//如果增加支付方式還是得增加else if

思路②

在思路①中存在一些問題枝笨,首當其沖的就是if else判斷問題。先思考一下這個if else的作用是什么揭蜒?

答:根據(jù)思路①描述伺帘,這個if else是用來確定采用哪種支付方式。

我們可以將這塊代碼抽離出來忌锯,讓對應的業(yè)務實現(xiàn)類實現(xiàn)自己的邏輯實現(xiàn)伪嫁,然后根據(jù)返回值true 或者false決定是否過濾掉這個業(yè)務實現(xiàn)類。接口定義如下偶垮,SupportBean是封裝的一個實體

boolean isSupport(SupportBean supportBean);

然后在各個業(yè)務實現(xiàn)類都實現(xiàn)自己的isSupport方法,偽代碼如下

@Override
public boolean isSupport(SupportBean supportBean) {
    if (supportBean.getType() == "xxx"){
        return true;
    }
    
    return false;
}

設計

注:只提供一個架子

接口定義

Service接口定義张咳,一個業(yè)務執(zhí)行方法execute(參數(shù)自行添加),一個isSupport方法(返回true或者false

public interface Service {

    void execute();

    boolean isSupport(SupportBean supportBean);
}

業(yè)務實現(xiàn)類

這里execute方法只是在控制臺打印字符串似舵。isSupport方法對SupportBean中的supportNum進行取余脚猾,判斷余數(shù)是否等于0,是則返回true砚哗。

類似的實現(xiàn)還有兩個龙助,這里就不貼出來了。

@Component
public class AServiceImpl implements Service {
    @Override
    public void execute() {
        System.out.println("A execute");
    }

    @Override
    public boolean isSupport(SupportBean supportBean) {
        return supportBean.getSupportNum() % 3 == 0;
    }
}

接下來在定義一個幫助類

幫助類

@Component
public class Helper {

    @Autowired
    private List<Service> services;

    public void execute(SupportBean supportBean){

        Service s = services.stream()
                .filter((service) -> service.isSupport(supportBean))
                .findFirst()//NPE異常
                .orElse(null);


        if (s != null){
            s.execute();
        }
    }
}

通過工具類的execute方法來獲取對應的業(yè)務實現(xiàn)類執(zhí)行的結果蛛芥,以及對傳入的參數(shù)進行校驗處理等提鸟。

需要注意的是Lambda表達式的findFirst()會出現(xiàn)NullPointException異常。因為filter對list進行過濾仅淑,會存在過濾完list的長度為0称勋,如果此時在調用findFirst則會拋出NullPointException⊙木梗可以將上面的代碼修改為如下代碼赡鲜,這樣就可以避免NPE了

Service s = services.stream()
        .filter((service) -> service.isSupport(supportBean))
        .map(Optional::ofNullable)
        .findFirst()
        .flatMap(Function.identity())
        .orElse(null);

測試

添加一個springboot測試類和一個測試方法。

在contextLoads測試中調用幫助類Helper的execute方法

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

    @Autowired
    private Helper Helper;

    @Test
    public void contextLoads() {
        Helper.execute(new SupportBean(3));
    }

}

測試結果

A execute

擴展

在Lambda表達式中是先將業(yè)務實現(xiàn)類進行過濾庐船,然后獲取第一個業(yè)務實現(xiàn)類并執(zhí)行银酬。

如果此時過濾存在多個業(yè)務實現(xiàn)類,而又不能確定優(yōu)先級筐钟,這時需要如何進行擴展呢揩瞪?

其實很簡單,先在Service接口中定義一個getPriority方法

int getPriority();

然后各自的實現(xiàn)類實現(xiàn)對應的getPriority方法

接著修改Lambda表達式即可盗棵,在filter后增加sorted方法即可對業(yè)務實現(xiàn)類進行排序

Service s = services.stream()
        .filter((service) -> service.isSupport(supportBean))
        .sorted(Comparator.comparing(Service::getPriority))
        .map(Optional::ofNullable)
        .findFirst()
        .flatMap(Function.identity())
        .orElse(null);

總結

整個大體框架基本都搭建完成壮韭,如需擴展只需要增加對應的業(yè)務實現(xiàn)類北发,而不用去修改其他類的代碼。就連之前設計的枚舉都可以不用喷屋,可擴展性大大提升琳拨。如需使用,只需修改對應的入?yún)⒑蛯拿Q即可屯曹。
Github地址
如果對你有收獲狱庇,歡迎star、歡迎fork
如果你也有類似的經(jīng)驗恶耽,歡迎加入密任,一起共建

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市偷俭,隨后出現(xiàn)的幾起案子浪讳,更是在濱河造成了極大的恐慌,老刑警劉巖涌萤,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淹遵,死亡現(xiàn)場離奇詭異,居然都是意外死亡负溪,警方通過查閱死者的電腦和手機透揣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來川抡,“玉大人辐真,你說我怎么就攤上這事⊙碌蹋” “怎么了侍咱?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長倘感。 經(jīng)常有香客問我放坏,道長咙咽,這世上最難降的妖魔是什么老玛? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮钧敞,結果婚禮上蜡豹,老公的妹妹穿的比我還像新娘。我一直安慰自己溉苛,他們只是感情好镜廉,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著愚战,像睡著了一般娇唯。 火紅的嫁衣襯著肌膚如雪齐遵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天塔插,我揣著相機與錄音梗摇,去河邊找鬼。 笑死想许,一個胖子當著我的面吹牛伶授,可吹牛的內容都是我干的。 我是一名探鬼主播流纹,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼糜烹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了漱凝?” 一聲冷哼從身側響起疮蹦,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤窍荧,失蹤者是張志新(化名)和其女友劉穎氏淑,沒想到半個月后岩臣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窥浪,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡刚陡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年唆鸡,在試婚紗的時候發(fā)現(xiàn)自己被綠了趾诗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痹届。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡贮尖,死狀恐怖笛粘,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情湿硝,我是刑警寧澤薪前,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站关斜,受9級特大地震影響示括,放射性物質發(fā)生泄漏。R本人自食惡果不足惜痢畜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一垛膝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧丁稀,春花似錦吼拥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至授账,卻和暖如春枯跑,著一層夾襖步出監(jiān)牢的瞬間惨驶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工敛助, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留敞咧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓辜腺,卻偏偏與公主長得像休建,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子评疗,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,192評論 25 707
  • 用兩張圖告訴你测砂,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,734評論 2 59
  • 親愛的自己百匆,大雪下了一天一夜砌些,早上起來,只看見外面是一個銀裝素裹的世界加匈。這場大雪給我們的出行帶來了很多不便存璃。大家都...
    冬季飄雪閱讀 102評論 0 1
  • 聽完“VVG Chin Chin 開幕講座”,受益頗深雕拼,尤其是和朱平先生對生活理念上達成了很多共識之處纵东,巧妙的是,...
    KJWANG閱讀 490評論 0 0
  • 你只是路過我的心間 我卻需要一生去忘卻 忘不了你在操場上奔跑的樣子 忘不了你皺眉頭的樣子 忘不了春風吹拂你劉海的樣...
    阿亮的月亮閱讀 229評論 1 5