博客原文地址:折騰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)算法的某些步驟。
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;
}
第一個(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;
}
有的時(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);
}
}
@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);
}
}
總體上來講,抽象類中定義了算法的框架,然后把部分算法步驟抽象出來供子類實(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
。
模板方法經(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)
當(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)