国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JAVA8-lambda表達式8:在設(shè)計模式-模板方法中的應(yīng)用

這篇具有很好參考價值的文章主要介紹了JAVA8-lambda表達式8:在設(shè)計模式-模板方法中的應(yīng)用。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

傳送門

JAVA8-lambda表達式1:什么是lambda表達式

JAVA8-lambda表達式2:常用的集合類api

JAVA8-lambda表達式3:并行流,提升效率的利器?

JAVA8-lambda表達式4:Optional用法

java8-lambda表達式5:toMap引發(fā)的線上故障

JAVA8-lambda表達式6:重構(gòu)和定制收集器

JAVA8-lambda表達式7:重要的函數(shù)接口

如何看待寫代碼這件事

最近在公司寫代碼(包括看代碼),突然有一點小小的感嘆。好多人整天研究什么高并發(fā),高可用,分布式,開口架構(gòu)閉口新技術(shù),就是不愿意花時間把自己的JAVA代碼寫的好一點。

把代碼寫好就是給自己印的最好的名片,也是對同事最大的負責!

可惜好多人不這樣認為,或者說可能是現(xiàn)在環(huán)境就是這樣吧:面試各種的造火箭,考算法導(dǎo)致從業(yè)者只能投其所好,刷題/刷各種高大上的所謂架構(gòu)技術(shù),而忽視一個最本質(zhì)的前提!

那就是技術(shù)是為業(yè)務(wù)服務(wù)的,絕大部分的公司是用不上所謂的大廠架構(gòu)的,強行匹配只會適得其反。

有空還是多琢磨琢磨怎么把那點JAVA代碼寫的更好吧。

這里的說法有點屬于"夾帶私貨"了,太過片面了,切勿對號入座。

什么是模板方法

在很早以前(真的是很早了,看了下發(fā)布日期是2018年2月?。?,學(xué)習過模板方法,它屬于常用的設(shè)計中的一種。當時里面介紹的例子取自《Head First設(shè)計模式》,所以文章算作是翻譯過來的。例子比較簡單,實現(xiàn)也是用的繼承+多態(tài)的。而還有一種很常用的模板方法,就是一個類+靜態(tài)方法,使用者直接通過靜態(tài)方法來調(diào)用!

Template.execute(a,b);
  • Template為類名
  • execute為方法
  • a,b為參數(shù)

在上面的調(diào)用中,Template.execute是不會變化,顧名思義就是模板方法的意思。而a,b則是需要調(diào)用方傳遞的參數(shù),必須是模板規(guī)定的類型。下面就以一個實際場景來看看如何抽象一個模板方法。

接口調(diào)用場景

對于JAVA程序員來說,spring肯定繞不開的結(jié)。當需要寫一個后端接口的時候,通過springMVC可以很方便的來實現(xiàn),比如在Oauth2系列7:授權(quán)碼和訪問令牌的頒發(fā)流程是怎樣實現(xiàn)的?里面提到的準備工作-驗證基本信息:

@RestController
@RequestMapping("/auth")
public class OauthController
{
    
    @GetMapping("/authorize")
    public void authorize(@RequestParam("response_type") String responseType, @RequestParam("client_id") String clientId,
                          @RequestParam("redirect_uri") String redirectUri, String scope)
    {
        
    }
}

還有驗證客戶端-生成訪問令牌:

@PostMapping("/token")
    public TokenModel getToken(@RequestBody GetTokenRequest getTokenRequest) {
        // 獲取令牌前置檢驗
        preGetTokenCheck(getTokenRequest);
 
        // 檢驗授權(quán)碼
        checkCode(getTokenRequest.getCode());
 
        // 生成t訪問令牌
        TokenModel tokenModel = generateToken();
        return tokenModel;
    }
private TokenModel generateToken() {
        // 獲取code信息,比如從redis
       // CodeModel codeModel = getCode;
        TokenModel tokenModel = new TokenModel();
        tokenModel.setAccessToken(UUID.randomUUID().toString());
        tokenModel.setExpiresIn(3600);
        tokenModel.setRefreshToken(UUID.randomUUID().toString());
        // tokenModel.setScope(codeModel.getScope);
        return tokenModel;
    }
  • 在類上打上注解RestController或Controller,現(xiàn)在一般自動轉(zhuǎn)換json就用RestController
  • 在方法上打上注解RequestMapping或GetMapping/PostMapping等,表示這個是一個接口方法
  • 在方法里面打上注解RequestParam或PathVariable,用來獲取參數(shù)

大致按照這3個步驟來操作,剩下的主要就是業(yè)務(wù)代碼編寫了(實際項目里面也沒有什么大的區(qū)別)。一般項目會分層,簡單的就三層:Web/Service/Dao。

  • Web表示展示層:接口的入?yún)@取,參數(shù)檢驗;日志打?。豁憫?yīng)轉(zhuǎn)換/返回(包括異常處理)
  • Service就是業(yè)務(wù)層:處理業(yè)務(wù)邏輯的,是方法的主體代碼
  • Dao層稱為存儲層:一般表示db處理,也可以是其它持久操作

模板方法

根據(jù)上面簡單三層的理解,定義一個模板方法出來:

@Slf4j
public class WebTemplate
{
    
    public static String execute(String req)
    {
        try
        {
            // 1:打印入?yún)?            log.info("方法參數(shù):{}", req);
            // 2:參數(shù)檢驗
            // TODO
            // 3:業(yè)務(wù)方法
        }
        catch (Exception e)
        {
            // 4:異常處理
            return "fail";
        }
        return "success";
    }
}

這里定義了模板方法的步驟:

  • 入?yún)㈩愋停ㄈ绻巧厦娴睦又荒艿腟tring肯定有局限性),最好支持泛型,比如都繼承Request基類
  • 參數(shù)打?。簩?shù)都打印出來,方便統(tǒng)計排查
  • 參數(shù)檢驗:對輸入?yún)?shù)進行檢驗,如果不符合條件則拋出異常,讓步驟4異常來統(tǒng)一處理
  • 業(yè)務(wù)方法執(zhí)行:對于這種業(yè)務(wù)方法的執(zhí)行,可以定義一個接口讓調(diào)用方來實現(xiàn)
  • 異常執(zhí)行:異??梢苑譃闃I(yè)務(wù)/全局異常,進行統(tǒng)一的處理,直接拋出或轉(zhuǎn)換成對應(yīng)異常碼
  • 組裝響應(yīng):響應(yīng)可以自定義,比如如上的異常碼/異常信息
  • 后置處理:可以在方法結(jié)束時,進行需要的后置處理,比如打印日志,方便后續(xù)監(jiān)控

由此可見一個完整模板方法類似如下:

package com.tw.tsm.base.template;

import com.tw.tsm.base.request.BaseRequestDTO;
import com.tw.tsm.base.response.BaseResponseDTO;
import lombok.extern.slf4j.Slf4j;

/**
 * 模板方法類
 */
@Slf4j
public class WebTemplate
{
    
    /**
     * 模板方法
     * @param req 請求參數(shù)
     * @param res 響應(yīng)參數(shù)
     * @param callback 回調(diào)方法
     * @param <T>
     * @param <R>
     */
    public static <T extends BaseRequestDTO, R extends BaseResponseDTO> void execute(T req, R res, ServiceCallback callback)
    {
        try
        {
            // 1:打印入?yún)?            log.info("方法參數(shù):{}", req);
            // 2:參數(shù)檢驗
            callback.check(req);
            // 3:業(yè)務(wù)方法
            callback.doService(req);
        }
        catch (Exception e)
        {
            // 4:異常處理
        }
        finally
        {
            log.info("處理結(jié)果:{}", res);
        }
    }
}


/**
 * 請求基類
 */
public class BaseRequestDTO
{
}


/**
 * 響應(yīng)基類
 */
@Data
public class BaseResponseDTO<T>
{
    /** 錯誤碼 */
    private String code;
    
    /** 錯誤信息 */
    private String msg;
    
    /** 返回內(nèi)容 */
    private T data;
}

/**
 * 模板處理接口
 * 
 * @param <T>
 */
public interface ServiceCallback<T>
{
    void check(T req);
    
    void doService(T req);
}

至此,模板方法已經(jīng)初具雛形,對于調(diào)用方來說,即可如下:

WebTemplate.execute(req, new BaseResponseDTO(), new ServiceCallback() {
            @Override
            public void check(Object req) {
                // 參數(shù)檢驗
            }

            @Override
            public void doService(Object req) {
                // 業(yè)務(wù)方法
            }
        });

異常處理?

上面的模板方法,統(tǒng)一捕獲了異常Exception,這樣所有的異常都會被處理。不過在很多時候,可能需要對異常進行分類處理,比如將異常分為業(yè)務(wù)/系統(tǒng)異常:

  • 對于業(yè)務(wù)異常希望明確提示調(diào)用方,告訴它失敗的原因:比如參數(shù)不合法,重復(fù)提交,資源不存在等
  • 對于系統(tǒng)異常,比如db連接超時,第三方服務(wù)不可用,Npe異常等又不希望直接返回給調(diào)用者:因為這種錯誤一般不是邏輯錯誤,調(diào)用者感知了也解決不了;再者可能會暴露代碼堆棧信息,也不太安全。所以這種一般處理是返回默認的提示,比如"系統(tǒng)繁忙,請稍候重試"

基于此,定義一個異常類:CheckedException讓它繼承自RuntimeException表示業(yè)務(wù)異常,跟Exception做區(qū)分:

/**
 * 檢驗異常
 */
@Data
@RequiredArgsConstructor
public class CheckedException extends RuntimeException
{
    
    /** 錯誤碼 */
    private String code;
    
    /** 錯誤信息 */
    private String msg;
}

在模板方法里面,加入CheckException處理:

/**
 * 模板方法類
 */
@Slf4j
public class WebTemplate
{
    
    /**
     * 模板方法
     * @param req 請求參數(shù)
     * @param res 響應(yīng)參數(shù)
     * @param callback 回調(diào)方法
     * @param <T>
     * @param <R>
     */
    public static <T extends BaseRequestDTO, R extends BaseResponseDTO> void execute(T req, R res, ServiceCallback callback)
    {
        try
        {
            // 1:打印入?yún)?            log.info("方法參數(shù):{}", req);
            // 2:參數(shù)檢驗
            callback.check(req);
            // 3:業(yè)務(wù)方法
            callback.doService(req);
        }
        catch (Exception e)
        {
            // 4:異常處理
            handleException(e, res);
        }
        finally
        {
            log.info("處理結(jié)果:{}", res);
        }
    }
    
    /**
     * 異常處理
     * @param e
     * @param response
     */
    private static void handleException(Exception e, BaseResponseDTO response)
    {
        if (e instanceof CheckedException)
        {
            CheckedException ex = (CheckedException)e;
            ex.setCode(ex.getCode());
            ex.setMsg(ex.getMsg());
            return;
        }
        // 設(shè)置默認異常
        // TODO
    }
}

異常碼

在模板類中單獨定義了一個方法handleException來處理異常:如果是業(yè)務(wù)異常,則將異常中的錯誤碼/錯誤信息填充到響應(yīng)里面,如果是系統(tǒng)異常則填充默認異常。因為這里定義的只有一個異常類CheckException來表示所有的業(yè)務(wù)異常,所以對于業(yè)務(wù)異常需要單獨定義一個類來表示不同的場景:

/**
 * 通用錯誤碼
 */
@AllArgsConstructor
public enum ComErrorCode
{
    
    /** 缺少參數(shù) */
    PARAM_MISS("E01000", "缺少參數(shù)"),
    /** 系統(tǒng)繁忙,請稍候重試 */
    SYSTEM_ERROR("E01999", "系統(tǒng)繁忙,請稍候重試");
    
    @Getter
    private String code;
    
    @Getter
    private String msg;
}

模板方法補充如下:

/**
 * 模板方法類
 */
@Slf4j
public class WebTemplate
{
    
    /**
     * 模板方法
     * @param req 請求參數(shù)
     * @param res 響應(yīng)參數(shù)
     * @param callback 回調(diào)方法
     * @param <T>
     * @param <R>
     */
    public static <T extends BaseRequestDTO, R extends BaseResponseDTO> void execute(T req, R res, ServiceCallback callback)
    {
        try
        {
            // 1:打印入?yún)?            log.info("方法參數(shù):{}", req);
            // 2:參數(shù)檢驗
            callback.check(req);
            // 3:業(yè)務(wù)方法
            callback.doService(req);
        }
        catch (Exception e)
        {
            // 4:異常處理
            handleException(e, res);
        }
        finally
        {
            log.info("處理結(jié)果:{}", res);
        }
    }
    
    /**
     * 異常處理
     * @param e
     * @param response
     */
    private static void handleException(Exception e, BaseResponseDTO response)
    {
        if (e instanceof CheckedException)
        {
            CheckedException ex = (CheckedException)e;
            ex.setCode(ex.getCode());
            ex.setMsg(ex.getMsg());
            return;
        }
        // 設(shè)置默認異常
        response.setCode(ComErrorCode.SYSTEM_ERROR.getCode());
        response.setMsg(ComErrorCode.SYSTEM_ERROR.getMsg());
    }
}

lambda在模板方法中的應(yīng)用

既然是要用lambda表達式在模板方法中應(yīng)用,所以就不能像剛才那樣對于回調(diào)函數(shù)直接用匿名類,這里就改造一下:文章來源地址http://www.zghlxwxcb.cn/news/detail-619903.html

/**
 * 模板回調(diào)函數(shù)
 * 
 * @param <T>
 */
@FunctionalInterface
public interface ServiceCallback<T>
{
    default void check(T req)
    {
    }
    
    void doService(T req);
}


 WebTemplate.execute(req, new BaseResponseDTO(), request -> {
        });
  • 首先改造一下回調(diào)函數(shù),增加@FunctionalInterface注解,表示這是一個函數(shù)式接口
  • 將check()方法聲明為default,這里java8的默認方法
  • 最后用lambda實現(xiàn)業(yè)務(wù)處理邏輯

到了這里,關(guān)于JAVA8-lambda表達式8:在設(shè)計模式-模板方法中的應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Java8新特性1——函數(shù)式接口&lambda表達式

    注:以下內(nèi)容基于Java 8,所有代碼都已在Java 8環(huán)境下測試通過 目錄: Java8新特性1——函數(shù)式接口lambda表達式 Java8新特性2——方法引用 Java8新特性3——Stream 如果在一個接口中, 有且只有一個抽象方法 ,則該接口被稱為函數(shù)式接口。如: 注: 可以在接口前使用 @FunctionalInt

    2024年02月10日
    瀏覽(47)
  • 進階JAVA篇- Lambda 表達式與 Lambda 表達式的省略規(guī)則

    進階JAVA篇- Lambda 表達式與 Lambda 表達式的省略規(guī)則

    目錄 ? ? ? ? 1.0 什么是 Lambda 表達式? ? ? ? ? 1.1 既然跟匿名內(nèi)部類相關(guān),先來回顧匿名內(nèi)部類。 ? ? ? ? ?1.2 Lambda 表達式與匿名內(nèi)部類之間的關(guān)系。 ? ? ? ? 1.3 函數(shù)式接口 ? ? ? ? 1.4 在具體代碼中來操作一下 ? ? ? ? 2.0?Lambda 表達式省略規(guī)則 ??????? ?Lambda 表達

    2024年02月08日
    瀏覽(29)
  • Java- Lambda表達式

    目錄 一、Lambda簡介 二、Lambda使用前提 三、Lambda語法 1.操作符 a.\\\"-\\\" ?b.\\\"::\\\" 2.格式? a.無參數(shù) b.有參數(shù) 四、Lambda演化過程 五、Lambda實現(xiàn)排序 Lambda 表達式,也可稱為閉包,它是推動 Java 8 發(fā)布的最重要新特性。Lambda 允許把函數(shù)作為一個方法的參數(shù)(函數(shù)作為參數(shù)傳遞進方法中)

    2024年02月03日
    瀏覽(28)
  • Java Lambda表達式

    1.1 函數(shù)式編程思想概括 在數(shù)學(xué)中,函數(shù)就是有輸入量、輸出量的一套計算方案,也就是“拿數(shù)據(jù)做操作” 面向?qū)ο笏枷霃娬{(diào)“必須通過對象的形式來做事情” 函數(shù)式思想則盡量忽略面

    2024年02月07日
    瀏覽(42)
  • Java Lambda 表達式

    Java Lambda 表達式

    ??wei_shuo的個人主頁 ??wei_shuo的學(xué)習社區(qū) ??Hello World ! Java Lambda 表達式是 Java 8 引入的一種函數(shù)式編程特性,它是一種輕量級的匿名函數(shù),允許我們將函數(shù)作為方法的參數(shù)進行傳遞。Lambda 表達式可以理解為是一種簡潔的方式來表示可傳遞的代碼塊,它可以替代傳統(tǒng)的匿名內(nèi)

    2024年02月08日
    瀏覽(34)
  • Lambda表達式(JAVA)

    Lambda表達式(JAVA)

    注:如果沒有學(xué)過 匿名內(nèi)部類 和 接口 不推薦往下看。 (parameters) - expression 或 (parameters) -{ statements; } parameters:表示參數(shù)列表; -:可理解為“被用于”的意思; expression:表示一條語句; statements:表示多條語句。 Lambda可以理解為:Lambda就是匿名內(nèi)部類的簡化。 lambda表達式

    2024年02月08日
    瀏覽(28)
  • 【JAVA】包裝類、正則表達式、Arrays類、Lambda表達式

    包裝類是8種基本數(shù)據(jù)類型對應(yīng)的引用類型 作用:后期的集合和泛型不支持基本類型,只能使用包裝類 基本數(shù)據(jù)類型和其對應(yīng)的引用數(shù)據(jù)類型的變量可以互相賦值 基本數(shù)據(jù)類型 引用數(shù)據(jù)類型 byte Byte short Short int Integer long Long char Character float Float double Double boolean Boolean 包裝類

    2024年02月13日
    瀏覽(33)
  • java lambda表達式詳解

    java lambda表達式詳解

    我們知道,在Java中,接口是不能實例化的,但是接口對象可以指向它的實現(xiàn)類對象。如果接口連實現(xiàn)對象都沒有呢?那還可以使用匿名類的方式,如下: 復(fù)制 但是,使用匿名內(nèi)部的方式,代碼量其實并不是非常簡潔,而為了使代碼更加的簡潔,Java引進了 Lambda 表達式的寫法,

    2024年02月03日
    瀏覽(34)
  • Java學(xué)習——lambda表達式

    Java學(xué)習——lambda表達式

    什么是Lambda表達式? 可以將Lambda表達式理解為一個匿名函數(shù); Lambda表達式允許將一個函數(shù)作為另外一個函數(shù)的參數(shù); 我們可以把 Lambda 表達式理解為是一段可以傳遞的代碼(將代碼作為實參),也可以理解為函數(shù)式編程, 將一個函數(shù)作為參數(shù)進行傳遞 。 為什么要引入Lambda表

    2024年02月04日
    瀏覽(38)
  • Java中的lambda表達式

    Java中的lambda表達式

    目錄 一、背景 二、lambada表達式的基本使用 三、變量捕獲 四、lambda在集合中的使用(map和set) 五、優(yōu)缺點 一、背景 (1)、lambda表達式的定義: (2)、lambda表達式的語法: (3)、函數(shù)式接口 二、lambada表達式的基本使用 (1)沒有使用lambda表達式,簡單調(diào)用函數(shù)式接口展

    2024年02月08日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包