什麼是設計模式?
一些經驗總結的最佳實踐!
是不是必須要用?
並不是,但是既然已經說是最佳實踐了,該用的地方,你不用,就有些違背常理了。
一、單例
這個或許是最最最常見,也是最最最常用的了。
爲什麼要用單例模式?
因爲只需要一個對象就夠了(有時候只能有一個,有時候是不需要有多個)。
對象的創建和銷燬也是成本。
1、Kafka 消息發送
比如,你要發 kafka 消息,你要創建一個 Producer 對象,因爲是 Producer 線程安全的,所以一般創建一個對象就夠了。
借用官方的一個建議:
2、Spring 容器 bean
Spring 容器管理的對象默認創建模式爲單例。當然你也可以根據實際業務對不同的對象設置不同的創建模式。
singleton: (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
需要說明的是,這個單例只是針對一個容器。
3、本地緩存
使用 Guava 本地緩存來加速業務響應。這個對於一個業務模塊也只需要創建一個,否則就會發生混亂了。
4、線程池
grpc 的線程池。
二、門面
門面模式或者也叫外觀模式。
意在屏蔽複雜性,通過一個簡潔的門面與外界進行交互。
1、信息輸出
比如,另外一個客服系統需要調取系列的用戶信息,包括基本信息,註冊、登錄信息,粉絲、關注信息,認證信息等等。
對於業務組來說,可能每一項都有現成的接口輸出。
但是,如果直接將這麼老多接口直接丟出去,似乎也顯得有些不合適:信息整合容易出問題;繁多的接口交互浪費網絡資源,影響業務響應時延,也容易破壞信息展現的完整性。
這裏就可以將所需的不同信息接口邏輯進行整體的封裝,輸出一個單一的功能接口來做門面接口。
2、Netty 的 Channel
Channel是一個接口,而且是一個很大的接口,我們稱之爲“大而全”,囊括了server端及client端接口所需要的接口。
Channel是一個門面,封裝了包括網絡I/O及相關的所有操作。
Channel聚合了包括網絡讀寫、鏈路管理、網絡連接信息、獲取EventLoop、Pipeline等相關功能類;統一分配,調度實現相應場景的功能。
3、BeanDefinitionLoader
BeanDefinitionLoader 用於從底層資源加載 bean 定義信息,包括 xml、JavaConfig。
是基於 AnnotatedBeanDefinitionReader、XmlBeanDefinitionReader、ClassPathBeanDefinitionScanner 的門面模式。
三、觀察者
當對象間存在一對多關係時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬於行爲型模式
1、Guava EventBus
用戶信息修改後刷新整體緩存。
爲什麼使用它?
首先是異步需求:同步有針對性的信息修改。整體刷新邏輯作爲緩存一致性數據保障不應該佔用同步業務邏輯。
其次是解耦:用戶信息比較冗繁,相應的 reload 邏輯牽涉業務甚多。所以將這部分邏輯進行解耦分離。
2、ApplicationListener
Spring ApplicationListener 應用事件監聽接口,基於標準的 EventListener 接口,觀察者模式實現。
ApplicationContext 通過 ApplicationEvent 類及 ApplicationListener 接口來處理事件。容器內實現了 ApplicationListener 接口的對象能夠獲取任何 ApplicationEvent 發佈的事件。
四、策略
將軍,我這裏有錦囊三個,你且隨身帶着,路遇天門,打開錦囊一,得扣天門;路遇地門,打開錦囊二,得扣地門;路遇人門,打開錦囊三,得扣人門。
策略模式針對同一應用場景存在多種處理方式的情景。
1、發短信
一個公司會接很多外部短信通道,阿里、Tencent、Twilio 等。
發送方可能會指定特定的短信通道;發送手機號可能地屬國內或者或外;
針對這種應用場景,就可以根據相應的入參選取不同的短信通道執行相應的發送操作。
3、行爲驗證
針對不同用戶風險特徵,執行不同的安全級別驗證。
極驗驗證的滑塊、點選、語序、空間推理等。
3、JDK Comparator
Collections.sort(List
根據傳入的 Comparator 比較器對相應的列表進行排序