- 重學(xué)Java設(shè)計(jì)模式
- 付政委(小付哥)
- 1601字
- 2021-05-19 18:09:58
5.5 抽象工廠模式重構(gòu)代碼
接下來使用抽象工廠模式優(yōu)化代碼,也是一次代碼重構(gòu)。在前文介紹過,抽象工廠的實(shí)質(zhì)就是用于創(chuàng)建工廠的工廠??梢岳斫鉃橛腥齻€(gè)物料加工車間,其中任意兩個(gè)都可以組合出一個(gè)新的生產(chǎn)工廠,用于裝備汽車或縫紉機(jī)。另外,這里會(huì)使用代理類的方式實(shí)現(xiàn)抽象工廠的創(chuàng)建過程。而兩個(gè) Redis 集群服務(wù)相當(dāng)于兩個(gè)車間,兩個(gè)車間可以構(gòu)成兩個(gè)工廠。通過代理類的實(shí)現(xiàn)方式,可以非常方便地實(shí)現(xiàn)Redis服務(wù)的升級(jí),并且可以在真實(shí)的業(yè)務(wù)場(chǎng)景中做成一個(gè)引入的中間件,給各個(gè)需要升級(jí)的系統(tǒng)使用。這里還有非常重要的一點(diǎn),集群EGM和集群IIR在部分方法提供上略有不同,如方法名和參數(shù),因此需要增加一個(gè)適配接口。最終使用這個(gè)適配接口承接兩套集群服務(wù),做到統(tǒng)一的服務(wù)輸出。
5.5.1 工程結(jié)構(gòu)


整個(gè)抽象工廠代碼類關(guān)系如圖5-4所示。

圖5-4
結(jié)合以上抽象工廠的工程結(jié)構(gòu)和類關(guān)系,簡(jiǎn)要介紹這部分代碼包括的核心內(nèi)容。整個(gè)工程包結(jié)構(gòu)分為三塊:工廠包(factory)、工具包(util)和車間包(workshop)。
·工廠包:JDKProxyFactory、JDKInvocationHandler兩個(gè)類是代理類的定義和實(shí)現(xiàn),這部分代碼主要通過代理類和反射調(diào)用的方式獲取工廠及方法調(diào)用。
·工具包:ClassLoaderUtils類主要用于支撐反射方法調(diào)用中參數(shù)的處理。
·車間包:EGMCacheAdapter、IIRCacheAdapter兩個(gè)類主要是通過適配器的方式使用兩個(gè)集群服務(wù)。把兩個(gè)集群服務(wù)作為不同的車間,再通過抽象的代理工廠服務(wù)把每個(gè)車間轉(zhuǎn)換為對(duì)應(yīng)的工廠。這里需要強(qiáng)調(diào)一點(diǎn),抽象工廠并不一定必須使用目前的方式實(shí)現(xiàn)。這種使用代理和反射的方式是為了實(shí)現(xiàn)一個(gè)中間件服務(wù),給所有需要升級(jí) Redis 集群的系統(tǒng)使用。在不同的場(chǎng)景下,會(huì)有很多不同的變種方式實(shí)現(xiàn)抽象工廠。
5.5.2 定義集群適配器接口

適配器接口的作用是包裝兩個(gè)集群服務(wù),在前面已經(jīng)提到這兩個(gè)集群服務(wù)在一些接口名稱和入?yún)⒎矫娓鞑幌嗤孕枰M(jìn)行適配。同時(shí)在引入適配器后,也可以非常方便地?cái)U(kuò)展。
5.5.3 實(shí)現(xiàn)集群適配器接口
1.EGM集群:EGMCacheAdapter

2.IIR集群:IIRCacheAdapter

如果是兩個(gè)集群服務(wù)的統(tǒng)一包裝,可以看到這些方法名稱或入?yún)⒍家呀?jīng)統(tǒng)一。例如,IIR集群的iir.setExpire和EGM集群的egm.setEx都被適配成一個(gè)方法名稱——set方法。
5.5.4 代理方式的抽象工廠類
1.代理抽象工廠JDKProxyFactory

這里有一點(diǎn)非常重要,就是為什么選擇代理方式實(shí)現(xiàn)抽象工廠。
因?yàn)橐言瓎误wRedis服務(wù)升級(jí)為兩套 Redis 集群服務(wù),在不破壞原有單體Redis服務(wù)和實(shí)現(xiàn)類的情況下,也就是cn-bugstack-design-5.0-0 的 CacheServiceImpl,通過一個(gè)代理類的方式實(shí)現(xiàn)一個(gè)集群服務(wù)處理類,就可以非常方便地在Spring、SpringBoot等框架中通過注入的方式替換原有的CacheServiceImpl實(shí)現(xiàn)。這樣中間件設(shè)計(jì)思路的實(shí)現(xiàn)方式具備了良好的插拔性,并可以達(dá)到多組集群同時(shí)使用和平滑切換的目的。
getProxy方法的兩個(gè)入?yún)⒌淖饔萌缦拢?/p>
·Class cacheClazz:在模擬的場(chǎng)景中,不同的系統(tǒng)使用的 Redis 服務(wù)類名可能有所不同,通過這樣的方式便于實(shí)例化后的注入操作。
·Class<?extends ICacheAdapter>cacheAdapter:這個(gè)參數(shù)用于決定實(shí)例化哪套集群服務(wù)使用Redis功能。
2.反射調(diào)用方法JDKInvocationHandler

這部分是工廠被代理實(shí)現(xiàn)后的核心處理類,主要包括如下功能:
·相同適配器接口 ICacheAdapter 的不同 Redis 集群服務(wù)實(shí)現(xiàn),其具體調(diào)用會(huì)在這里體現(xiàn)。
·在反射調(diào)用過程中,通過入?yún)@取需要調(diào)用的方法名稱和參數(shù),可以調(diào)用對(duì)應(yīng)Redis集群中的方法。
抽象工廠搭建完成了,這部分抽象工廠屬于從中間件設(shè)計(jì)中抽取出來的最核心的內(nèi)容,如果需要在實(shí)際的業(yè)務(wù)中使用,則需要擴(kuò)充相應(yīng)的代碼,如注入的設(shè)計(jì)、配置的讀取、相關(guān)監(jiān)控和緩存使用開關(guān)等。
5.5.5 測(cè)試驗(yàn)證
1.單元測(cè)試


在測(cè)試方法中提供了兩套集群的工廠獲取及相應(yīng)方法的使用。通過代理的方式JDKProxyFactory.getProxy(CacheService.class,IIRCacheAdapter.class);獲取相應(yīng)的工廠。這里獲取的過程相當(dāng)于從車間中組合出新的工廠。最終在實(shí)際的使用中交給Spring進(jìn)行Bean注入,通過這樣的方式升級(jí)服務(wù)集群,就不需要所有的研發(fā)人員硬編碼了。即使有任何問題,也可以回退到原有的實(shí)現(xiàn)方式里。這種可插拔服務(wù)的優(yōu)點(diǎn)是易于維護(hù)和可擴(kuò)展。
2.測(cè)試結(jié)果

從測(cè)試結(jié)果來看運(yùn)行正常,升級(jí)完成。這種代碼的擴(kuò)展方式遠(yuǎn)比硬編碼 if…else好得多,既可擴(kuò)展又易維護(hù)。研發(fā)人員的技術(shù)棧、技術(shù)經(jīng)驗(yàn)會(huì)決定最終的執(zhí)行結(jié)果,有時(shí)候如果具備豐富的技能,即使在非常緊急的情況下,也可以做出非常完善的技術(shù)方案和落地結(jié)果。
- ASP.NET Core 5.0開發(fā)入門與實(shí)戰(zhàn)
- Three.js開發(fā)指南:基于WebGL和HTML5在網(wǎng)頁(yè)上渲染3D圖形和動(dòng)畫(原書第3版)
- Mastering Natural Language Processing with Python
- 鋒利的SQL(第2版)
- MongoDB權(quán)威指南(第3版)
- Android底層接口與驅(qū)動(dòng)開發(fā)技術(shù)詳解
- MATLAB 2020從入門到精通
- Julia數(shù)據(jù)科學(xué)應(yīng)用
- Python Programming for Arduino
- Puppet 5 Beginner's Guide(Third Edition)
- Cinder:Begin Creative Coding
- Learning jqPlot
- 從零開始:Qt可視化程序設(shè)計(jì)基礎(chǔ)教程
- Procedural Content Generation for Unity Game Development
- Android程序設(shè)計(jì):第2版