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

原來(lái)使用 Spring 實(shí)現(xiàn)策略模式可以這么簡(jiǎn)單!

開(kāi)發(fā) 架構(gòu)
策略模式作為一種軟件設(shè)計(jì)模式,指對(duì)象有某個(gè)行為,但是在不同的場(chǎng)景中,該行為有不同的實(shí)現(xiàn)算法,可以替代代碼中大量的 if-else。

[[379778]]

本文轉(zhuǎn)載自微信公眾號(hào)「武培軒」,作者武培軒 。轉(zhuǎn)載本文請(qǐng)聯(lián)系武培軒公眾號(hào)。

策略模式作為一種軟件設(shè)計(jì)模式,指對(duì)象有某個(gè)行為,但是在不同的場(chǎng)景中,該行為有不同的實(shí)現(xiàn)算法,可以替代代碼中大量的 if-else。

比如我們生活中的場(chǎng)景:買(mǎi)東西結(jié)賬可以使用微信支付、支付寶支付或者銀行卡支付,這些交易方式就是不同的策略。

那么在什么時(shí)候使用策略模式呢?

在《阿里巴巴Java開(kāi)發(fā)手冊(cè)》中有提到當(dāng)超過(guò) 3 層的 if-else 的邏輯判斷代碼可以使用策略模式來(lái)實(shí)現(xiàn)。

在 Spring 中實(shí)現(xiàn)策略模式的方式有很多種,下面通過(guò)一個(gè)案例來(lái)演示下,比如有個(gè)需求需要實(shí)現(xiàn)支持第三方登錄,目前需要支持以下三種登錄方式:

  • 微信登錄
  • QQ 登錄
  • 微博登錄

下面將通過(guò)策略模式來(lái)實(shí)現(xiàn)這個(gè)需求,其中策略模式結(jié)構(gòu)如下圖所示:

策略模式結(jié)構(gòu)如下圖所示:

策略模式結(jié)構(gòu)

主要包括一個(gè)登錄接口類(lèi)和幾種登錄方式的實(shí)現(xiàn)方式,并利用簡(jiǎn)單工廠來(lái)獲取對(duì)應(yīng)的處理器。

定義策略接口

首先定義一個(gè)登錄的策略接口 LoginHandler,其中包括兩個(gè)方法:

獲取策略類(lèi)型的方法

處理策略邏輯的方法

  1. public interface LoginHandler<T extends Serializable> { 
  2.  
  3.     /** 
  4.      * 獲取登錄類(lèi)型 
  5.      * 
  6.      * @return 
  7.      */ 
  8.     LoginType getLoginType(); 
  9.  
  10.     /** 
  11.      * 登錄 
  12.      * 
  13.      * @param request 
  14.      * @return 
  15.      */ 
  16.     LoginResponse<String, T> handleLogin(LoginRequest request); 

其中,LoginHandler 的 getLoginType 方法用來(lái)獲取登錄的類(lèi)型(即策略類(lèi)型),用于根據(jù)客戶(hù)端傳遞的參數(shù)直接獲取到對(duì)應(yīng)的策略實(shí)現(xiàn)。

客戶(hù)端傳遞的相關(guān)參數(shù)都被封裝為 LoginRequest,傳遞給 handleLogin 進(jìn)行處理。

  1. @Data 
  2. public class LoginRequest { 
  3.  
  4.     private LoginType loginType; 
  5.  
  6.     private Long userId; 

其中,根據(jù)需求定義登錄類(lèi)型枚舉如下:

  1. public enum LoginType { 
  2.     QQ, 
  3.     WE_CHAT, 
  4.     WEI_BO; 

實(shí)現(xiàn)策略接口

在定義好策略接口后,我們就需要根據(jù)各種第三方登錄來(lái)實(shí)現(xiàn)對(duì)應(yīng)的處理邏輯就可以了。

微信登錄

  1. @Component 
  2. public class WeChatLoginHandler implements LoginHandler<String> { 
  3.  
  4.     private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
  5.  
  6.     /** 
  7.      * 獲取登錄類(lèi)型 
  8.      * 
  9.      * @return 
  10.      */ 
  11.     @Override 
  12.     public LoginType getLoginType() { 
  13.         return LoginType.WE_CHAT; 
  14.     } 
  15.  
  16.     /** 
  17.      * 登錄 
  18.      * 
  19.      * @param request 
  20.      * @return 
  21.      */ 
  22.     @Override 
  23.     public LoginResponse<String, String> handleLogin(LoginRequest request) { 
  24.         logger.info("微信登錄:userId:{}", request.getUserId()); 
  25.         String weChatName = getWeChatName(request); 
  26.         return LoginResponse.success("微信登錄成功", weChatName); 
  27.     } 
  28.  
  29.     private String getWeChatName(LoginRequest request) { 
  30.         return "wupx"
  31.     } 

QQ 登錄

  1. @Component 
  2. public class QQLoginHandler implements LoginHandler<Serializable> { 
  3.  
  4.     private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
  5.  
  6.     /** 
  7.      * 獲取登錄類(lèi)型 
  8.      * 
  9.      * @return 
  10.      */ 
  11.     @Override 
  12.     public LoginType getLoginType() { 
  13.         return LoginType.QQ; 
  14.     } 
  15.  
  16.     /** 
  17.      * 登錄 
  18.      * 
  19.      * @param request 
  20.      * @return 
  21.      */ 
  22.     @Override 
  23.     public LoginResponse<String, Serializable> handleLogin(LoginRequest request) { 
  24.         logger.info("QQ登錄:userId:{}", request.getUserId()); 
  25.         return LoginResponse.success("QQ登錄成功"null); 
  26.     } 

微博登錄

  1. @Component 
  2. public class WeiBoLoginHandler implements LoginHandler<Serializable> { 
  3.  
  4.     private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
  5.  
  6.     /** 
  7.      * 獲取登錄類(lèi)型 
  8.      * 
  9.      * @return 
  10.      */ 
  11.     @Override 
  12.     public LoginType getLoginType() { 
  13.         return LoginType.WEI_BO; 
  14.     } 
  15.  
  16.     /** 
  17.      * 登錄 
  18.      * 
  19.      * @param request 
  20.      * @return 
  21.      */ 
  22.     @Override 
  23.     public LoginResponse<String, Serializable> handleLogin(LoginRequest request) { 
  24.         logger.info("微博登錄:userId:{}", request.getUserId()); 
  25.         return LoginResponse.success("微博登錄成功"null); 
  26.     } 

創(chuàng)建策略的簡(jiǎn)單工廠

  1. @Component 
  2. public class LoginHandlerFactory implements InitializingBean, ApplicationContextAware { 
  3.     private static final Map<LoginType, LoginHandler<Serializable>> LOGIN_HANDLER_MAP = new EnumMap<>(LoginType.class); 
  4.     private ApplicationContext appContext; 
  5.  
  6.     /** 
  7.      * 根據(jù)登錄類(lèi)型獲取對(duì)應(yīng)的處理器 
  8.      * 
  9.      * @param loginType 登錄類(lèi)型 
  10.      * @return 登錄類(lèi)型對(duì)應(yīng)的處理器 
  11.      */ 
  12.     public LoginHandler<Serializable> getHandler(LoginType loginType) { 
  13.         return LOGIN_HANDLER_MAP.get(loginType); 
  14.     } 
  15.  
  16.     @Override 
  17.     public void afterPropertiesSet() throws Exception { 
  18.         // 將 Spring 容器中所有的 LoginHandler 注冊(cè)到 LOGIN_HANDLER_MAP 
  19.         appContext.getBeansOfType(LoginHandler.class) 
  20.                 .values() 
  21.                 .forEach(handler -> LOGIN_HANDLER_MAP.put(handler.getLoginType(), handler)); 
  22.     } 
  23.  
  24.     @Override 
  25.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
  26.         appContext = applicationContext; 
  27.     } 

我們讓 LoginHandlerFactory實(shí)現(xiàn) InitializingBean 接口,在 afterPropertiesSet 方法中,基于 Spring 容器將所有 LoginHandler 自動(dòng)注冊(cè)到 LOGIN_HANDLER_MAP,從而 Spring 容器啟動(dòng)完成后, getHandler 方法可以直接通過(guò) loginType 來(lái)獲取對(duì)應(yīng)的登錄處理器。

創(chuàng)建登錄服務(wù)

在登錄服務(wù)中,我們通過(guò) LoginHandlerFactory 來(lái)獲取對(duì)應(yīng)的登錄處理器,從而處理不同類(lèi)型的第三方登錄:

  1. @Service 
  2. public class LoginServiceImpl implements LoginService { 
  3.     @Autowired 
  4.     private LoginHandlerFactory loginHandlerFactory; 
  5.  
  6.     @Override 
  7.     public LoginResponse<String, Serializable> login(LoginRequest request) { 
  8.         LoginType loginType = request.getLoginType(); 
  9.         // 根據(jù) loginType 找到對(duì)應(yīng)的登錄處理器 
  10.         LoginHandler<Serializable> loginHandler = 
  11.                 loginHandlerFactory.getHandler(loginType); 
  12.         // 處理登錄 
  13.         return loginHandler.handleLogin(request); 
  14.     } 

Factory 只負(fù)責(zé)獲取 Handler,Handler 只負(fù)責(zé)處理具體的登錄,Service 只負(fù)責(zé)邏輯編排,從而達(dá)到功能上的低耦合高內(nèi)聚。

測(cè)試

寫(xiě)一個(gè) Controller:

  1. @RestController 
  2. public class LoginController { 
  3.  
  4.     @Autowired 
  5.     private LoginService loginService; 
  6.  
  7.     /** 
  8.      * 登錄 
  9.      */ 
  10.     @PostMapping("/login"
  11.     public LoginResponse<String, Serializable> login(@RequestParam LoginType loginType, @RequestParam Long userId) { 
  12.         LoginRequest loginRequest = new LoginRequest(); 
  13.         loginRequest.setLoginType(loginType); 
  14.         loginRequest.setUserId(userId); 
  15.         return loginService.login(loginRequest); 
  16.     } 

然后用 Postman 測(cè)下下:

微信登錄

 

QQ登錄

是不是很簡(jiǎn)單呢?如果需求又要加需求,需要支持 GitHub 第三方登錄。

此時(shí)我們只需要添加一個(gè)新的策略實(shí)現(xiàn),然后在登錄枚舉中加入對(duì)應(yīng)的類(lèi)型即可:

  1. @Component 
  2. public class GitHubLoginHandler implements LoginHandler<Serializable> { 
  3.  
  4.     private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
  5.  
  6.     /** 
  7.      * 獲取登錄類(lèi)型 
  8.      * 
  9.      * @return 
  10.      */ 
  11.     @Override 
  12.     public LoginType getLoginType() { 
  13.         return LoginType.GIT_HUB; 
  14.     } 
  15.  
  16.     /** 
  17.      * 登錄 
  18.      * 
  19.      * @param request 
  20.      * @return 
  21.      */ 
  22.     @Override 
  23.     public LoginResponse<String, Serializable> handleLogin(LoginRequest request) { 
  24.         logger.info("GitHub登錄:userId:{}", request.getUserId()); 
  25.         return LoginResponse.success("GitHub登錄成功"null); 
  26.     } 

此時(shí)不需要修改任何代碼 ,因?yàn)?Spring 容器重啟時(shí)會(huì)自動(dòng)將 GitHubLoginHandler 注冊(cè)到 LoginHandlerFactory 中,使用 Spring 實(shí)現(xiàn)策略模式就是這么簡(jiǎn)單,還不快學(xué)起來(lái)!

 

責(zé)任編輯:武曉燕 來(lái)源: 武培軒
相關(guān)推薦

2020-09-25 07:49:36

策略模式Spring

2022-06-17 07:32:39

策略模式SpringBoot

2014-10-08 15:00:50

SUSE操作系統(tǒng)云計(jì)算

2021-04-19 05:42:51

Mmap文件系統(tǒng)

2010-08-02 13:55:20

2016-03-21 11:09:52

Tableau/大數(shù)據(jù)

2023-11-01 14:49:07

2020-11-02 14:38:56

Java 深度學(xué)習(xí)模型

2021-06-10 06:57:39

Redis存儲(chǔ)數(shù)據(jù)庫(kù)

2022-12-06 17:30:04

2019-03-15 10:55:12

通信系統(tǒng)手機(jī)

2023-09-22 08:00:00

分布式鎖Redis

2020-09-24 06:44:54

HTTPS網(wǎng)站 HTTP

2020-11-27 10:34:01

HTTPHTTPS模型

2025-05-08 09:31:06

2020-10-22 08:01:52

XMLJSON轉(zhuǎn)換

2014-11-25 15:02:01

客服系統(tǒng)

2025-03-20 12:33:36

2018-10-28 17:54:00

分布式事務(wù)數(shù)據(jù)

2019-05-27 14:03:48

開(kāi)發(fā)技能代碼
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 欧美aaaa视频| 亚洲欧美一区二区三区国产精品 | 精品国产乱码久久久久久影片 | 国产偷自视频区视频 | 亚洲欧美第一视频 | 欧美日韩在线观看视频网站 | 国产精品一区二区不卡 | 久精品久久| 久久在线看 | 国产高清在线精品 | 人人精品 | 欧美日韩在线一区二区 | 日韩成人在线观看 | 日本特黄a级高清免费大片 成年人黄色小视频 | 亚洲视频一区二区三区 | 久久久久久久网 | 成人精品一区 | 日韩伦理电影免费在线观看 | 午夜天堂精品久久久久 | 成人av资源在线 | 国产高清在线精品 | 欧美激情一区二区三区 | 中文字幕日韩欧美 | 欧美三区视频 | 国产精品毛片 | 日韩另类| 国产99精品 | 久久国产精彩视频 | 亚洲精品黄| 午夜男人天堂 | 全部免费毛片在线播放网站 | 欧美成人精品激情在线观看 | 在线观看中文视频 | 国产精品欧美一区二区三区 | 成人h视频在线观看 | 日韩成人免费视频 | 欧美爱爱视频网站 | 日本中文字幕一区 | 尤物在线精品视频 | 久久99精品久久久久子伦 | 女人精96xxx免费网站p |