<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          函數(shù)式編程是如何提升代碼的擴(kuò)展性

          共 3534字,需瀏覽 8分鐘

           ·

          2021-07-09 17:16


          軟件的發(fā)展大致經(jīng)歷三個(gè)階段


          • 第一階段(20世紀(jì)40年代中期到50年代中期),主要是科學(xué)與工程計(jì)算,處理對(duì)象為數(shù)值數(shù)據(jù),以個(gè)體方式使用機(jī)器(或匯編)語(yǔ)言編制程序

          • 第二階段(20世紀(jì)50年代中期到60年代后期),從高級(jí)程序設(shè)計(jì)語(yǔ)言出現(xiàn)到軟件工程提出以前。這個(gè)階段研究對(duì)象增加了并發(fā)程序,并著重研究高級(jí)程序設(shè)計(jì)語(yǔ)言、編譯程序、操作系統(tǒng)以及各種支撐軟件和應(yīng)用軟件

          • 第三階段(20世紀(jì)60年代后期軟件工程提出以來(lái)),由于大型軟件的開(kāi)發(fā)耗時(shí)耗力,任務(wù)重,需要采用合作的方式才能完成,所以引入軟件工程的理念來(lái)管理項(xiàng)目。


          從工程學(xué)角度來(lái)講,我們常說(shuō)的軟件工程一般采用面向?qū)ο缶幊?,差別在與使用的編程語(yǔ)言不同,有人習(xí)慣用java,有人喜歡C#,各有各的特色,除了語(yǔ)法上略有差異,其本質(zhì)都差不多,所以你可能會(huì)經(jīng)常聽(tīng)到有人說(shuō),只要你精通了一門(mén)語(yǔ)言,再學(xué)習(xí)其他語(yǔ)言,會(huì)感覺(jué)如有神助,基本也是這個(gè)道理。


          面向?qū)ο缶幊?/strong>


          首先我們來(lái)看下面向?qū)ο缶幊痰娜筇匦?/span>


          • 封裝

          • 繼承

          • 多態(tài)


          面向?qū)ο缶幊淌且环N具有對(duì)象概念的程序編程范型,它可能包含數(shù)據(jù)、屬性、代碼與方法。對(duì)象則指的是類(lèi)的實(shí)例。它將對(duì)象作為程序的基本單元,將程序和數(shù)據(jù)封裝其中,以提高軟件的可重用性、靈活性和可擴(kuò)展性,對(duì)象里的程序可以訪問(wèn)及修改對(duì)象相關(guān)聯(lián)的數(shù)據(jù)。在面向?qū)ο缶幊汤铮?jì)算機(jī)程序會(huì)被設(shè)計(jì)成彼此相關(guān)的對(duì)象。


          對(duì)象按照?qǐng)?zhí)行角色,可以分為數(shù)據(jù)對(duì)象、行為對(duì)象。我們常理解的面向?qū)ο缶幊痰哪J?,比如:y=f(x),其中x、y都是數(shù)據(jù)對(duì)象,通過(guò)行為對(duì)象F的方法運(yùn)算得到了加工后的對(duì)象y。


          我們具體看個(gè)示例:


          /** * @Author onlyone * <p> * 活動(dòng)模型 */public class Activity {
          private Long id; // 活動(dòng)id private String name; // 名稱(chēng) private String desc; // 描述 private Date time; // 活動(dòng)時(shí)間 private String publisher; // 發(fā)布人}


          按活動(dòng)id查找一個(gè)活動(dòng),代碼一般會(huì)這么寫(xiě)


          public Activity queryById(List<Activity> activityList, String id) {    for (Activity activity : activityList) {        if (id.equals(activity.getId())) {            return activity;        }    }    return null;}


          如果此時(shí)業(yè)務(wù)提出了一個(gè)新的需求,按名稱(chēng)來(lái)查詢活動(dòng),得嘞,又得重新造個(gè)輪子


          public Activity queryByName(List<Activity> activityList, String name) {    for (Activity activity : activityList) {        if (name.equals(activity.getId())) {            return activity;        }    }    return null;}



          過(guò)了幾天,業(yè)務(wù)產(chǎn)品又來(lái)找你了,想根據(jù)時(shí)間來(lái)查詢活動(dòng),此時(shí),你是不是有種崩潰的感覺(jué)。




          重構(gòu)是我們腦海閃現(xiàn)的第一念想,如何重構(gòu),卻讓我們陷入一臉懵逼的茫然狀態(tài)。三個(gè)需求,處理邏輯各不相同,如何復(fù)用抽???


          我們需要改變我們的思維方式,誰(shuí)規(guī)定調(diào)用方法傳入的實(shí)參一定是數(shù)值型對(duì)象,如果傳入一個(gè)函數(shù)表達(dá)式,能不能解決這個(gè)問(wèn)題?

          是不是有種豁然開(kāi)朗的感覺(jué)。




          函數(shù)式編程


          函數(shù)式編程第一個(gè)需要了解的概念就是函數(shù):


          • 函數(shù)可以按需創(chuàng)建

          • 函數(shù)可以當(dāng)作實(shí)參傳給另一個(gè)方法

          • 函數(shù)可以當(dāng)作另一個(gè)方法的返回值


          JDK 8 開(kāi)始引入函數(shù)式編程,并提供了很多預(yù)定義接口類(lèi),如 Predicates 用于判斷,函數(shù) Functions,生產(chǎn) Suppliers,消費(fèi) Consumers,比較 Comparators。


          代碼示例:https://github.com/aalansehaiyang/java8-tutorial


          本文的重構(gòu)思路就是采用Predicate接口,我們先來(lái)看些內(nèi)部結(jié)構(gòu)


          @FunctionalInterfacepublic interface Predicate<T> {    boolean test(T t);}


          /** * @Author onlyone * 面向函數(shù)編程 */public class FuncitionProgram {
          private List<Activity> activityList;
          /** * 基礎(chǔ)查詢骨架 */ Activity queryByPredicate(Predicate<Activity> predicate) { for (Activity activity : activityList) { if (predicate.test(activity)) { return activity; } } return null; }}



          按id查詢活動(dòng),傳入對(duì)應(yīng)的Predicate表達(dá)式


          public Activity queryById(String id) {    return queryByPredicate(activity -> id.equals(activity.getId()));}


          按名稱(chēng)查詢活動(dòng),傳入對(duì)應(yīng)的Predicate表達(dá)式


          public Activity queryByName(String name) {    return queryByPredicate(activity -> name.equals(activity.getName()));}


          是不是有種”牛逼“的感覺(jué)。低調(diào),優(yōu)化是永無(wú)止境,有沒(méi)有更好的優(yōu)化方式。


          作為一名架構(gòu)師,我們?cè)谧鱿到y(tǒng)架構(gòu)時(shí),為了滿足其高并發(fā)、擴(kuò)展性,一般會(huì)講究一個(gè)拆分原則,將一個(gè)復(fù)雜的業(yè)務(wù)域問(wèn)題拆分成一個(gè)個(gè)業(yè)務(wù)子域,降低系統(tǒng)的復(fù)雜度,也能滿足其后續(xù)的靈活擴(kuò)展。按照這個(gè)思路,我們繼續(xù)優(yōu)化,將Predicate 函數(shù)獨(dú)立出來(lái)。


          // id判斷函數(shù)public Predicate<Activity> idPredicate(String id) {    return activity -> id.equals(activity.getId());}
          // 名稱(chēng)判斷函數(shù)public Predicate<Activity> namePredicate(String name) { return activity -> name.equals(activity.getName());}


          我們提供了`原子化`函數(shù),具體怎么組裝,由上層的調(diào)用方根據(jù)業(yè)務(wù)需要自己來(lái)拼接。


          // 按id查詢活動(dòng)queryByPredicate(idPredicate(id));// 按名稱(chēng)查詢活動(dòng)queryByPredicate(namePredicate(name));// 按id、名稱(chēng)組合條件查詢活動(dòng)queryByPredicate(idPredicate(id).and(namePredicate(name)));


          畫(huà)外音:


          萬(wàn)事萬(wàn)物,由于都有其個(gè)性化特征,如果按常規(guī)方式,窮舉是很難滿足所有業(yè)務(wù)需求。但如果我們能按其特征抽取,封裝組件能力,由流程引擎根據(jù)業(yè)務(wù)訴求,自由組合,則能滿足其最大靈活性,更像一個(gè)軟件高手所為。


          本文的代碼示例已上傳到github


          https://github.com/aalansehaiyang/project-example

          推薦閱讀:
          數(shù)據(jù)庫(kù)連接池為什么首選Druid
          億級(jí)系統(tǒng)的Redis緩存如何設(shè)計(jì)
          學(xué)會(huì)這10個(gè)設(shè)計(jì)原則,離架構(gòu)師又進(jìn)了一步
          Spring Boot 集成 Kafka

          關(guān)號(hào)互聯(lián)網(wǎng)全棧架構(gòu),價(jià)。

          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  东方AV在线一 | 色五月av综合 | 亚洲88 | 无码人妻一级毛片免费 | 一极黄片在线免费收看 |