成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

折騰Java設(shè)計(jì)模式之模板方法模式

博客原文地址:折騰Java設(shè)計(jì)模式之模板方法模式

成都創(chuàng)新互聯(lián)公司是專業(yè)的十堰鄖陽網(wǎng)站建設(shè)公司,十堰鄖陽接單;提供網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè),網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行十堰鄖陽網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

模板方法模式

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

翻譯過來就是,把算法的框架定義好,可以將某些步抽象出來放到子類去實(shí)現(xiàn)。模板方法允許子類在不改變算法框架的情況下重新實(shí)現(xiàn)算法的某些步驟。

模板方法模式UML圖

UML圖

折騰Java設(shè)計(jì)模式之模板方法模式cdn.xitu.io/2019/4/1/169d676374d89d71?w=500&h=240&f=jpeg&s=12703">

抽象類AbstractClass定義了算法框架templateMethod()方法,其中有2個(gè)方法primitve1()primitve2()被抽象出來,子類SubClass1繼承了抽象類AbstractClass,從而實(shí)現(xiàn)了primitve1()primitve2()。

模板方法模式角色

抽象類(AbstractClass):定義了算法核心框架,同時(shí)把局部的算法行為封裝成步驟,讓子類去實(shí)現(xiàn)。

子類(SubClass):繼承了抽象類,實(shí)現(xiàn)抽象類中的抽象方法,具體實(shí)現(xiàn)了算法部分邏輯。

模板方法模式源碼示例

源碼地址:Template-method

抽象方法

先定義抽象類,抽象類AbstractProcessor中核心算法handle方法中大體分3部,第一先校驗(yàn)參數(shù)具體怎么校驗(yàn)放在子類中實(shí)現(xiàn),第二獲取結(jié)果也放在子類實(shí)現(xiàn),第三獲取結(jié)果后的操作也放在子類實(shí)現(xiàn)。

@Slf4j
public abstract class AbstractProcessor<P extends Request, R extends Response> {

    /**
     * 邏輯處理
     *
     * @param request
     * @return
     */
    public R handle(P request) {
        // 1.校驗(yàn)參數(shù)
        log.info("開始處理, 請求參數(shù)={}", request);
        validRequest(request);

        // 2.獲取結(jié)果
        R response = getResponse(request);
        log.info("獲取結(jié)果, 響應(yīng)結(jié)果={}", response);

        // 3.結(jié)果之后的處理
        afterHandle(response);
        return response;
    }

    /**
     * 結(jié)果之后的處理 可以更新其他業(yè)務(wù)或者處理緩存
     *
     * @param response
     */
    protected abstract void afterHandle(R response);

    /**
     * 校驗(yàn)請求參數(shù)
     *
     * @param request
     */
    protected void validRequest(P request) {
        if (Objects.isNull(request.getToken())) {
            throw new RuntimeException("token不能為空");
        }
        if (Objects.isNull(request.getVersion())) {
            throw new RuntimeException("version不能為空");
        }

        validRequestParam(request);
    }

    /**
     * 校驗(yàn)請求真正的參數(shù)
     * @param request
     */
    protected abstract void validRequestParam(P request);

    /**
     * 獲取到結(jié)果
     * @param request
     * @return
     */
    protected abstract R getResponse(P request);
}

基本請求

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class Request {

     private String version;

     private String token;
}

基本響應(yīng)

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class Response {

     private String msg;

     private int code;

     private boolean success;

}

子類實(shí)現(xiàn)

第一個(gè)子類實(shí)現(xiàn)

@Slf4j
public class OneProcessor extends AbstractProcessor<OneRequest, OneResponse> {

    public OneProcessor() {
        ProcessorFactory.putProcess("two", this);
    }

    @Override
    protected void afterHandle(OneResponse response) {
        log.info("處理One結(jié)果: {}", response.getOne());
    }

    @Override
    protected void validRequestParam(OneRequest request) {
        log.info("校驗(yàn)one參數(shù)...省略......");
    }

    @Override
    protected OneResponse getResponse(OneRequest request) {
        String name = request.getName();
                return OneResponse.builder()
                .one(name + "one")
                .success(true)
                .code(0)
                .msg("成功")
                .build();
    }
}

第一個(gè)子類的請求

@Data
@ToString(callSuper = true)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class OneRequest extends Request {

    private String name;

    @Builder.Default
    private int a = 0;

}

第一個(gè)子類的響應(yīng)

@Data
@ToString(callSuper = true)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class OneResponse extends Response {

    private String one;

}

第二個(gè)子類實(shí)現(xiàn)

@Slf4j
public class TwoProcessor extends AbstractProcessor<TwoRequest, TwoResponse> {

    public TwoProcessor() {
        ProcessorFactory.putProcess("two", this);
    }

    @Override
    protected void afterHandle(TwoResponse response) {
        log.info("處理結(jié)果TWO, {}", response);
    }

    @Override
    protected void validRequestParam(TwoRequest request) {
        log.info("校驗(yàn)TWO參數(shù)...省略......");
    }

    @Override
    protected TwoResponse getResponse(TwoRequest request) {
        Long id = request.getId();
        return TwoResponse.builder()
                .two("id為"+id)
                .success(true)
                .code(0)
                .msg("成功")
                .build();
    }
}

第二個(gè)子類的請求

@Data
@ToString(callSuper = true)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class TwoRequest extends Request {

    private Long id;
}

第二個(gè)子類的響應(yīng)

@Data
@ToString(callSuper = true)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class TwoResponse extends Response {

    private String two;
}

擴(kuò)展為工廠

有的時(shí)候我們定義的子類在Spring容器的時(shí)候由Spring定義好后,我們其實(shí)可以借用工廠模式方法,在子類初始化的時(shí)候就把子類放置在ProcessorFactory中,后續(xù)只需要根據(jù)key從中拿取即可,實(shí)際項(xiàng)目中用這種方式還是比較多的。

public class ProcessorFactory {

    private static Map<String, AbstractProcessor> factories = new HashMap();

    public static void putProcess(String key, AbstractProcessor process) {
        factories.put(key, process);
    }

    public static AbstractProcessor selectProcess(String key) {
        return factories.get(key);
    }

}

執(zhí)行程序

@Slf4j
public class TemplateMethodApplication {

    public static void main(String[] args) {
        OneRequest oneRequest = OneRequest.builder()
                .version("2312312")
                .token("23423")
                .name("張三")
                .build();
        new OneProcessor().handle(oneRequest);

        log.info("--------------------------");

        TwoRequest twoRequest = TwoRequest.builder()
                .version("2312312")
                .token("23423")
                .id(23456L)
                .build();
        new TwoProcessor().handle(twoRequest);

    }
}

結(jié)果

折騰Java設(shè)計(jì)模式之模板方法模式

總體上來講,抽象類中定義了算法的框架,然后把部分算法步驟抽象出來供子類實(shí)現(xiàn),有的時(shí)候有些方法只有個(gè)別子類會(huì)去實(shí)現(xiàn),我們可以在抽象類中實(shí)現(xiàn)為空實(shí)現(xiàn),在有需要的子類中我們可以覆蓋抽象類的實(shí)現(xiàn),這樣避免了所有的子類都去實(shí)現(xiàn),其實(shí)不關(guān)心的話都是空實(shí)現(xiàn)了。本示例用到了lombok@SuperBuilder特性,可能在下載完完整的代碼后會(huì)出現(xiàn)編譯錯(cuò)誤,這是因?yàn)?code>Lombok的插件暫時(shí)還不支持@SuperBuilder。

模板方法模式總結(jié)

模板方法經(jīng)常和其他模式混合使用,比如工廠、策略等等。其實(shí)在Spring中大量使用了模板方法模式,其實(shí)也不光在Spring中,像平時(shí)jdbcTemplate或者redisTemplate,像這種帶有Template的。

優(yōu)點(diǎn)1、封裝不變部分,擴(kuò)展可變部分。 2、提取公共代碼,便于維護(hù)。 3、行為由父類控制,子類實(shí)現(xiàn)。

缺點(diǎn)每一個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類來實(shí)現(xiàn),導(dǎo)致類的個(gè)數(shù)增加,使得系統(tǒng)更加龐大。

使用場景1、有多個(gè)子類共有的方法,且邏輯相同。 2、重要的、復(fù)雜的方法,可以考慮作為模板方法。

注意事項(xiàng)為防止惡意操作,一般模板方法都加上 final 關(guān)鍵詞。

參考

模板模式|菜鳥教程

Template method pattern

歡迎關(guān)注我的微信公眾號(hào)

折騰Java設(shè)計(jì)模式之模板方法模式

當(dāng)前文章:折騰Java設(shè)計(jì)模式之模板方法模式
當(dāng)前地址:http://jinyejixie.com/article34/ijjspe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、企業(yè)網(wǎng)站制作全網(wǎng)營銷推廣、網(wǎng)頁設(shè)計(jì)公司、ChatGPT、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作
将乐县| 任丘市| 广东省| 都昌县| 德江县| 志丹县| 荔波县| 迭部县| 浏阳市| 平潭县| 尉犁县| 会理县| 黄浦区| 韶关市| 平罗县| 伊春市| 措勤县| 花莲县| 弋阳县| 康乐县| 文成县| 大余县| 罗定市| 喀什市| 正镶白旗| 遵义市| 赤城县| 青神县| 察隅县| 长春市| 磐石市| 德清县| 怀来县| 同心县| 新化县| 麻城市| 老河口市| 菏泽市| 松原市| 喀喇沁旗| 高雄县|