<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
不知道大家在專案中有沒有遇到過這樣的場景,根據傳入的型別,呼叫介面不同的實現類或者說服務,比如根據檔案的型別使用 CSV解析器或者JSON解析器,在呼叫的使用者端一般都是用if else
去做判斷,比如型別等於JSON,我就用JSON解析器,那如果新加一個型別的解析器,是不是呼叫的使用者端還要修改呢?這顯然太耦合了,本文就介紹一種方法,服務定位元型樣Service Locator Pattern
來解決,它幫助我們消除緊耦合實現及其依賴性,並提出將服務與其具體類解耦。
我們通過一個例子來告訴你如何使用Service Locator Pattern
。
假設我們有一個從各種來源獲取資料的應用程式,我們必須解析不同型別的檔案,比如解析CSV檔案和JSON檔案。
定義一個型別的列舉
public enum ContentType { JSON, CSV }
定義一個解析的介面
public interface Parser { List parse(Reader r); }
根據不同的檔案型別有不同的實現類
// 解析csv @Component public class CSVParser implements Parser { @Override public List parse(Reader r) { .. } } // 解析json @Component public class JSONParser implements Parser { @Override public List parse(Reader r) { .. } }
最後寫一個呼叫的使用者端,通過switch case
根據不同的型別呼叫不同的實現
@Service public class Client { private Parser csvParser, jsonParser; @Autowired public Client(Parser csvParser, Parser jsonParser) { this.csvParser = csvParser; this.jsonParser = jsonParser; } public List getAll(ContentType contentType) { .. switch (contentType) { case CSV: return csvParser.parse(reader); case JSON: return jsonParser.parse(reader); .. } } .. }
可能大部分人都是像上面一樣的方式實現的,也能正常執行,那深入思考下,存在什麼問題嗎?
現在假如產品經理提出了一個新需求要支援XML型別的檔案,是不是使用者端也要修改程式碼,需要在switch case
中新增新的型別,這就導致使用者端和不同的解析器緊密耦合。
那麼有什麼更好的方法呢?
沒錯,那就是用上我們的服務定位元型樣Service Locator Pattern
。
讓我們定義我們的服務定 位器介面ParserFactory
, 它有一個接受內容型別引數並返回Parser
的方法。
public interface ParserFactory { Parser getParser(ContentType contentType); }
我們設定ServiceLocatorFactoryBean
使用ParserFactory
作為服務定 位器介面,ParserFactory
這個介面不需要寫實現類。
@Configuration public class ParserConfig { @Bean("parserFactory") public FactoryBean serviceLocatorFactoryBean() { ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean(); // 設定服務定位介面 factoryBean.setServiceLocatorInterface(ParserFactory.class); return factoryBean; } }
設定解析器Bean的名稱為型別名稱,方便服務定位
// 設定bean的名稱和型別一致 @Component("CSV") public class CSVParser implements Parser { .. } @Component("JSON") public class JSONParser implements Parser { .. } @Component("XML") public class XMLParser implements Parser { .. }
修改列舉, 新增XML
public enum ContentType { JSON, CSV, XML }
最後用使用者端呼叫,直接根據型別呼叫對應的解析器,沒有了switch case
@Service public class Client { private ParserFactory parserFactory; @Autowired public Client(ParserFactory parserFactory) { this.parserFactory = parserFactory; } public List getAll(ContentType contentType) { .. // 關鍵點,直接根據型別獲取 return parserFactory .getParser(contentType) .parse(reader); } .. }
嘿嘿,我們已經成功地實現了我們的目標。現在再加新的型別,我們只要擴充套件新增新的解析器就行,再也不用修改使用者端了,滿足開閉原則。
如果你覺得Bean的名稱直接使用型別怪怪的,這邊可以建議你按照下面的方式來。
public enum ContentType { JSON(TypeConstants.JSON_PARSER), CSV(TypeConstants.CSV_PARSER), XML(TypeConstants.XML_PARSER); private final String parserName; ContentType(String parserName) { this.parserName = parserName; } @Override public String toString() { return this.parserName; } public interface TypeConstants { String CSV_PARSER = "csvParser"; String JSON_PARSER = "jsonParser"; String XML_PARSER = "xmlParser"; } } @Component(TypeConstants.CSV_PARSER) public class CSVParser implements Parser { .. } @Component(TypeConstants.JSON_PARSER) public class JSONParser implements Parser { .. } @Component(TypeConstants.XML_PARSER) public class XMLParser implements Parser { .. }
通過前面的例子,想必大家基本知道服務定 位器模式如何使用了吧,現在我們深入剖析下。
服務定 位器模式消除了使用者端對具體實現的依賴。以下引自 Martin Fowler
的文章總結了核心思想: “服務定 位器背後的基本思想是擁有一個知道如何獲取應用程式可能需要的所有服務的物件。因此,此應用程式的服務定 位器將有一個在需要時返回“服務”的方法。”
Spring
的ServiceLocatorFactoryBean
實現了 FactoryBean
介面,建立了Service Factory
服務工廠Bean
。
我們通過使用服務定 位器模式實現了一種擴充套件 Spring 控制反轉的絕妙方法。它幫助我們解決了依賴注入未提供最佳解決方案的用例。也就是說,依賴注入仍然是首選,並且在大多數情況下不應使用服務定 位器來替代依賴注入。
到此這篇關於Spring你不知道的一種解耦模式的文章就介紹到這了,更多相關Spring解耦模式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45