成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

設(shè)計(jì)模式之模版方法模式

開發(fā) 前端
在設(shè)計(jì)模式中的模版方法模式,也是可以理解為一種規(guī)范模版。主要是提升我們代碼的復(fù)用性,以及擴(kuò)展等問題。

[[405818]]

大家每到一家公司都會(huì)發(fā)現(xiàn),每個(gè)公司都會(huì)有一個(gè)規(guī)范,比如說請(qǐng)假流程規(guī)范,代碼規(guī)范等等。每個(gè)公司都有這個(gè)流程,只是里面的具體執(zhí)行條件不一樣而已。

在設(shè)計(jì)模式中的模版方法模式,也是可以理解為一種規(guī)范模版。主要是提升我們代碼的復(fù)用性,以及擴(kuò)展等問題。

這樣的模板方法在我們當(dāng)舔狗跟妹妹們聊天的時(shí)候也是可以用到的,比如這樣一個(gè)模板:

“寶,XXXX了,XXXX什么XX?X你的XXX”

當(dāng)我拿到這樣一個(gè)模板的時(shí)候,我就可以舉一反三直接套用了,我們直接填參數(shù)就可以了,比如:

“寶,我打疫苗了,打的什么苗 ,愛你的每一秒 ”

“寶,我做核酸了,做的什么酸,得不到你的心酸”

“寶,今天去輸液了,輸?shù)氖裁匆海肽愕囊?rdquo;

...........

好了言歸正傳,在框架中模版方法模式也是很常見的。

今天就具體來聊聊設(shè)計(jì)模式中行為型設(shè)計(jì)模式中模版方法模式。

設(shè)計(jì)模式系列往期文章:

  • 單例模式
  • 工廠模式
  • 流程引擎
  • 建造者模式
  • 原型模式
  • 責(zé)任鏈模式
  • 觀察者模式
  • 策略模式

大綱

還是老規(guī)矩從上圖五個(gè)方面來分別具體和大家聊聊模版方法模式

定義

模版方法模式的定義以及目的?

  • 定義:模板方法模式在一個(gè)方法中定義一個(gè)算法骨架,并將某些步驟推遲到子類中實(shí)現(xiàn)。模板方法模式可以讓子類在不改變算法整體結(jié)構(gòu)的情況下,重新定義算法中的某些步驟
  • 目的:1.使用模版方法模式的目的是避免編寫重復(fù)代碼,以便開發(fā)人員可以專注于核心業(yè)務(wù)邏輯的實(shí)現(xiàn)
  • 2.解決接口與接口實(shí)現(xiàn)類之間繼承矛盾問題
  • 以上定義來自《設(shè)計(jì)模式之美》

結(jié)構(gòu)圖:

  • AbstractTemplate(抽象模版):定義一系列抽象方法,或者實(shí)現(xiàn)的方法,又或者是鉤子方法。即:定義流程
  • ConcreteTemplate(具體模版):實(shí)現(xiàn)父類抽象方法,基于本身不同的模版業(yè)務(wù)邏輯,實(shí)現(xiàn)不同的業(yè)務(wù)邏輯代碼。即:抽象方法實(shí)現(xiàn)相同,內(nèi)部邏輯不同

整個(gè)結(jié)構(gòu)圖看起來還是很簡(jiǎn)單的,但是還是要理解設(shè)計(jì)模式解決什么問題。

代碼實(shí)現(xiàn)?還是舉例吧。

還是以上面的請(qǐng)假舉例吧,假設(shè)現(xiàn)在A公司請(qǐng)假需要直屬領(lǐng)導(dǎo)審批以及通知HR有人請(qǐng)假了就可以了,B公司需要直屬領(lǐng)導(dǎo),部門負(fù)責(zé)人審批最后通知HR,方能完成整個(gè)請(qǐng)假流程。那作為OA辦公流程怎么去處理這個(gè)問題嘛?直接看代碼實(shí)現(xiàn)吧!

  1. public abstract class AskForLeaveFlow { 
  2.  
  3.     // 一級(jí)組長(zhǎng)直接審批 
  4.     protected abstract void firstGroupLeader(String name); 
  5.  
  6.     // 二級(jí)組長(zhǎng)部門負(fù)責(zé)人審批 
  7.     protected void secondGroupLeader(String name) { 
  8.     } 
  9.  
  10.     // 告知HR有人請(qǐng)假了 
  11.     private final void notifyHr(String name) { 
  12.         System.out.println("當(dāng)前有人請(qǐng)假了,請(qǐng)假人:" + name); 
  13.     } 
  14.  
  15.     // 請(qǐng)假流模版 
  16.     public void askForLeave(String name) { 
  17.         firstGroupLeader(name); 
  18.         secondGroupLeader(name); 
  19.         notifyHr(name); 
  20.     } 
  21.  

首先還是定義一個(gè)請(qǐng)假流程,其中:

  • firstGroupLeader方法為abstract修飾,則作為子類都是必須要實(shí)現(xiàn)的
  • secondGroupLeader 二級(jí)領(lǐng)導(dǎo)審批,在子類中可以重寫,也可不重寫
  • notifyHr 方法為通知HR,已經(jīng)內(nèi)部實(shí)現(xiàn)

最后一個(gè)askForLeave請(qǐng)假流程方法,把以上模版方法串起來

  1. public class CompanyA extends AskForLeaveFlow { 
  2.      
  3.     @Override 
  4.     protected void firstGroupLeader(String name) { 
  5.         System.out.println("CompanyA 組內(nèi)有人請(qǐng)假,請(qǐng)假人:" + name); 
  6.     } 
  7.  
  8. public class CompanyB extends AskForLeaveFlow { 
  9.     @Override 
  10.     protected void firstGroupLeader(String name) { 
  11.         System.out.println("CompanyB 組內(nèi)有人請(qǐng)假,請(qǐng)假人:" + name); 
  12.     } 
  13.     @Override 
  14.     protected void secondGroupLeader(String name){ 
  15.         System.out.println("CompanyB 部門有人請(qǐng)假,請(qǐng)假人:" + name); 
  16.     } 

在CompanyA以及CompanyB中,secondGroupLeader二級(jí)領(lǐng)導(dǎo)可以選擇重寫或者不重寫,這個(gè)類模版方法簡(jiǎn)稱為鉤子方法。

  1. public class testTemplate { 
  2.     public static void main(String[] args) { 
  3.         // 公司A請(qǐng)假流程模版 
  4.         AskForLeaveFlow companyA = new CompanyA(); 
  5.         companyA.askForLeave("敖丙"); 
  6.         // 結(jié)果:CompanyA 組內(nèi)有人請(qǐng)假,請(qǐng)假人:敖丙 
  7.         //       當(dāng)前有人請(qǐng)假了,請(qǐng)假人:敖丙 
  8.  
  9.         AskForLeaveFlow companyB = new CompanyB(); 
  10.         companyB.askForLeave("敖丙"); 
  11.         // 結(jié)果:CompanyB 組內(nèi)有人請(qǐng)假,請(qǐng)假人:敖丙 
  12.         //      CompanyB 部門有人請(qǐng)假,請(qǐng)假人:敖丙 
  13.         //      當(dāng)前有人請(qǐng)假了,請(qǐng)假人:敖丙 
  14.     } 

最后就是看測(cè)試dome結(jié)果了。companyA和companyB分別輸出了對(duì)應(yīng)的請(qǐng)假流程。

細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn)了,做為模版方法中里面除了可以有抽象方法外,還可以有具體的實(shí)現(xiàn)方法以及鉤子方法。

所以大家在應(yīng)用的過程可以多考慮考慮在內(nèi)部定義模版方法時(shí),應(yīng)該定義成抽象方法還是其它的。

框架中的應(yīng)用

模版方法模式在我們常見的Java的框架中也是非常常見的,只是可能我們平時(shí)沒有注意到這一點(diǎn)而已。

第一個(gè):首先我們學(xué)SpringMVC的時(shí)候,最開始都會(huì)寫一些Servlet來作為處理一些post或者get請(qǐng)求等。

這里直接看這個(gè)源碼大家就可以發(fā)現(xiàn)這也是直接使用模版方法模式的思想,期間在HttpServlet 繼承GenericServlet中也還是模版方法的體現(xiàn),這說明了可以多次抽象構(gòu)建模版。

第二個(gè):常見問的文件流中,Java IO 類中的InputStream、OutputStream、Reader、Writer等都能看到模版方法模式的身影。

上面是我貼出的部分InputStream的源碼,主要看這個(gè)read模版方法,也就是模版方法模式的體現(xiàn)。

當(dāng)然IO類中還有很多其他的,我就不一一貼源碼出來了,感情興趣的同學(xué),可以自己打開源碼了解了解。

業(yè)務(wù)舉例

在業(yè)務(wù)中怎么使用模版方法?

首先需要理解模版方法它是為了增加代碼的復(fù)用性,以及擴(kuò)展性而存在的,所以本著這個(gè)思想我還是給大家舉一個(gè)例子吧。

之前寫責(zé)任鏈模式最后給大家舉例商品詳情,這次還是用商品詳情,但是用模版方法模式來實(shí)現(xiàn)這個(gè)問題,理解為商詳2.0版本。

商品詳情展示我們可以是分模塊展示的,比如頭圖,商品信息,sku信息,配送地址,分期付費(fèi)等等。

那么怎么進(jìn)行組裝到商品詳情的展示呢?

流程圖:

可以看到一個(gè)請(qǐng)求過來,可以有模塊組裝器選擇組裝返回結(jié)果。

  • 提一個(gè)點(diǎn),在第二步請(qǐng)求的模塊的時(shí)候?yàn)榱藴p少整個(gè)鏈路的請(qǐng)求時(shí)間可以考慮是串行,或者并行(開線程池處理)。

接下來直接看代碼吧

  1. public abstract class AbstractTemplateBlock<T> { 
  2.     // 組裝結(jié)果 
  3.     public T template(ModelContainer modelContainer) { 
  4.         T block = initBlock(); 
  5.         try { 
  6.             this.doWork(modelContainer, block); 
  7.         } catch (Exception e) { 
  8.             // 可以選擇捕獲異常,是中斷流程,還是只打印日志,不中斷流程 
  9.         } 
  10.         return block; 
  11.     } 
  12.     // 初始化構(gòu)建返回結(jié)果模型 
  13.     protected abstract T initBlock(); 
  14.     // 定義抽象模版 
  15.     protected abstract void doWork(ModelContainer modelContainer, T block) throws Exception; 

還是先創(chuàng)建模版Block

  1. @Component 
  2. public class ItemInfoBlock extends AbstractTemplateBlock<ItemInfoBlock.ItemInfo> { 
  3.     @Override 
  4.     protected ItemInfoBlock.ItemInfo initBlock() { 
  5.         return new ItemInfoBlock.ItemInfo(); 
  6.     } 
  7.  
  8.     // 模擬業(yè)務(wù)邏輯,組裝返回商品信息模塊數(shù)據(jù) 
  9.     @Override 
  10.     protected void doWork(ModelContainer modelContainer, ItemInfo block) throws Exception { 
  11.         block.setItemId(123L); 
  12.         block.setItemName("測(cè)試"); 
  13.     } 
  14.     @Data 
  15.     public static class ItemInfo { 
  16.         private Long itemId; 
  17.         private String itemName; 
  18.     } 

這里只寫了一個(gè)ItemInfoBlock,其他的模塊也是這一樣的寫法,所以就不全寫出來了。

  1. public static void main(String[] args) { 
  2.     // 1.模擬獲取SpringBean 
  3.     ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 
  4.     ItemInfoBlock itemInfoBlock = (ItemInfoBlock) applicationContext.getBean("itemInfoBlock"); 
  5.  
  6.   // 2. ModelContainer可以理解為貫穿上下文中的請(qǐng)求參數(shù),或者一些組裝數(shù)據(jù)需要的預(yù)加載數(shù)據(jù) 
  7.    ModelContainer modelContainer  = new ModelContainer(); 
  8.    // 3. 獲取返回結(jié)果 
  9.    ItemInfoBlock.ItemInfo itemInfo = itemInfoBlock.template(modelContainer); 
  10.    System.out.println(JSON.toJSONString(itemInfo)); 
  11.    // 結(jié)果:{"itemId":123,"itemName":"測(cè)試"

最后就是看測(cè)試demo了,可以看到再每一個(gè)模塊中都是有一個(gè)AbstractTemplateBlock,內(nèi)部包含doWork抽象方法,由子類去實(shí)現(xiàn)當(dāng)前自己的業(yè)務(wù)邏輯。

同時(shí)第三步獲取返回結(jié)果時(shí),我只是單獨(dú)列出來,大家可以根據(jù)實(shí)際情況還能做改造。比如說返回map結(jié)構(gòu)等 mapKey 是模塊名稱,value是數(shù)據(jù)。

當(dāng)前這種組裝商品詳情的模式也是比較常見的一種方式。代碼的復(fù)用性高,同時(shí)擴(kuò)展性也有一定的體現(xiàn),符合模版方法模式的思想。

總結(jié)

模版方法模式的特點(diǎn)大家應(yīng)該也能體會(huì)到了,適用場(chǎng)景還是為了增加代碼的復(fù)用性,以及擴(kuò)展性。

還是那句話存在即合理,不要因設(shè)計(jì)模式而在寫代碼時(shí)強(qiáng)行嵌套。合理的學(xué)習(xí)每種設(shè)計(jì)模式適合場(chǎng)景,解決什么問題。

 

責(zé)任編輯:姜華 來源: 三太子敖丙
相關(guān)推薦

2012-07-11 08:51:51

設(shè)計(jì)模式

2022-02-11 10:22:48

模版模式語言

2020-08-21 07:23:50

工廠模式設(shè)計(jì)

2015-09-08 13:39:10

JavaScript設(shè)計(jì)模式

2012-01-13 15:59:07

2021-12-24 07:50:45

責(zé)任鏈模式設(shè)計(jì)

2023-09-04 13:14:00

裝飾器設(shè)計(jì)模式

2021-06-29 08:54:23

設(shè)計(jì)模式代理模式遠(yuǎn)程代理

2021-06-09 08:53:34

設(shè)計(jì)模式策略模式工廠模式

2012-02-29 09:41:14

JavaScript

2020-08-11 11:20:30

Typescript設(shè)計(jì)模式

2023-12-12 11:09:55

模板方法模式python設(shè)計(jì)模式

2009-01-15 10:55:29

JavaScript設(shè)計(jì)模式抽象工廠

2021-06-22 15:27:13

設(shè)計(jì)模式迭代器模式Java

2021-09-16 06:44:05

組合模式設(shè)計(jì)

2022-03-25 11:01:28

Golang裝飾模式Go 語言

2010-04-13 08:54:28

PHP設(shè)計(jì)模式命令模式

2021-12-01 07:38:27

設(shè)計(jì)模式規(guī)格模式Specificati

2023-12-13 13:28:16

裝飾器模式Python設(shè)計(jì)模式

2010-03-25 08:52:30

PHP設(shè)計(jì)模式代理模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩一区二区在线视频 | 亚洲精品国产第一综合99久久 | 欧美日韩电影一区 | 日韩成人影院在线观看 | 国产一区二区视频在线观看 | 在线色网址 | 中文字幕av免费 | 亚洲精品日日夜夜 | 国产精品一区二区av | 超碰97人人人人人蜜桃 | 99精品视频免费在线观看 | 亚洲国产精品精华素 | 91视频一区 | 人人操日日干 | 欧美日韩电影一区 | 亚洲九九 | 91av视频在线观看 | 国产成人免费视频网站高清观看视频 | 日本不卡一区二区三区在线观看 | 免费小视频在线观看 | 国产日韩精品一区二区三区 | 精品日韩在线观看 | 中文字幕一区二区三区精彩视频 | 亚洲精品在线国产 | 国产欧美精品一区 | 成人免费在线视频 | 日本爱爱 | 97福利在线 | 成人午夜看片 | 天天操,夜夜爽 | 成人一区二区三区在线观看 | 午夜小电影 | 欧美一级免费 | 亚洲一区二区在线视频 | 蜜桃视频在线观看免费视频网站www | 日韩一区二区三区视频 | 91婷婷韩国欧美一区二区 | 91成人免费观看 | 日韩在线视频一区二区三区 | 麻豆国产一区二区三区四区 | 欧美一级电影免费 |