www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]前言平時(shí)我們寫代碼呢,多數(shù)情況都是流水線式寫代碼,基本就可以實(shí)現(xiàn)業(yè)務(wù)邏輯了。如何在寫代碼中找到樂(lè)趣呢,我覺(jué)得,最好的方式就是:使用設(shè)計(jì)模式優(yōu)化自己的業(yè)務(wù)代碼。今天跟大家聊聊日常工作中,我都使用過(guò)哪些設(shè)計(jì)模式。工作中常用到哪些設(shè)計(jì)模式1.策略模式1.1業(yè)務(wù)場(chǎng)景假設(shè)有這樣的業(yè)務(wù)場(chǎng)景,...

前言

平時(shí)我們寫代碼呢,多數(shù)情況都是流水線式寫代碼,基本就可以實(shí)現(xiàn)業(yè)務(wù)邏輯了。如何在寫代碼中找到樂(lè)趣呢,我覺(jué)得,最好的方式就是:使用設(shè)計(jì)模式優(yōu)化自己的業(yè)務(wù)代碼。今天跟大家聊聊日常工作中,我都使用過(guò)哪些設(shè)計(jì)模式。


實(shí)戰(zhàn)!工作中常用到哪些設(shè)計(jì)模式工作中常用到哪些設(shè)計(jì)模式

1.策略模式

1.1 業(yè)務(wù)場(chǎng)景

假設(shè)有這樣的業(yè)務(wù)場(chǎng)景,大數(shù)據(jù)系統(tǒng)把文件推送過(guò)來(lái),根據(jù)不同類型采取不同的解析方式。多數(shù)的小伙伴就會(huì)寫出以下的代碼:


if(type=="A"){
//按照A格式解析

}else if(type=="B"){
//按B格式解析
}else{
//按照默認(rèn)格式解析
}
這個(gè)代碼可能會(huì)存在哪些問(wèn)題呢?


  • 如果分支變多,這里的代碼就會(huì)變得臃腫,難以維護(hù),可讀性低。
  • 如果你需要接入一種新的解析類型,那只能在原有代碼上修改。
說(shuō)得專業(yè)一點(diǎn)的話,就是以上代碼,違背了面向?qū)ο缶幊痰拈_(kāi)閉原則以及單一原則。


  • 開(kāi)閉原則(對(duì)于擴(kuò)展是開(kāi)放的,但是對(duì)于修改是封閉的):增加或者刪除某個(gè)邏輯,都需要修改到原來(lái)代碼
  • 單一原則(規(guī)定一個(gè)類應(yīng)該只有一個(gè)發(fā)生變化的原因):修改任何類型的分支邏輯代碼,都需要改動(dòng)當(dāng)前類的代碼。
如果你的代碼就是醬紫:有多個(gè)if...else等條件分支,并且每個(gè)條件分支,可以封裝起來(lái)替換的,我們就可以使用策略模式來(lái)優(yōu)化。


1.2 策略模式定義

策略模式定義了算法族,分別封裝起來(lái),讓它們之間可以相互替換,此模式讓算法的變化獨(dú)立于使用算法的的客戶。這個(gè)策略模式的定義是不是有點(diǎn)抽象呢?那我們來(lái)看點(diǎn)通俗易懂的比喻:


假設(shè)你跟不同性格類型的小姐姐約會(huì),要用不同的策略,有的請(qǐng)電影比較好,有的則去吃小吃效果不錯(cuò),有的去逛街買買買最合適。當(dāng)然,目的都是為了得到小姐姐的芳心,請(qǐng)看電影、吃小吃、逛街就是不同的策略。


策略模式針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類中,從而使得它們可以相互替換。


1.3 策略模式使用

策略模式怎么使用呢?醬紫實(shí)現(xiàn)的:


  • 一個(gè)接口或者抽象類,里面兩個(gè)方法(一個(gè)方法匹配類型,一個(gè)可替換的邏輯實(shí)現(xiàn)方法)
  • 不同策略的差異化實(shí)現(xiàn)(就是說(shuō),不同策略的實(shí)現(xiàn)類)
  • 使用策略模式

1.3.1 一個(gè)接口,兩個(gè)方法

public interface IFileStrategy {

//屬于哪種文件解析類型
FileTypeResolveEnum gainFileType();

//封裝的公用算法(具體的解析方法)
void resolve(Object objectparam);
}

1.3.2 不同策略的差異化實(shí)現(xiàn)

A 類型策略具體實(shí)現(xiàn)


@Component
public class AFileResolve implements IFileStrategy {

@Override
public FileTypeResolveEnum gainFileType() {
return FileTypeResolveEnum.File_A_RESOLVE;
}

@Override
public void resolve(Object objectparam) {
logger.info("A 類型解析文件,參數(shù):{}",objectparam);
//A類型解析具體邏輯
}
}
B 類型策略具體實(shí)現(xiàn)


@Component
public class BFileResolve implements IFileStrategy {

@Override
public FileTypeResolveEnum gainFileType() {
return FileTypeResolveEnum.File_B_RESOLVE;
}


@Override
public void resolve(Object objectparam) {
logger.info("B 類型解析文件,參數(shù):{}",objectparam);
//B類型解析具體邏輯
}
}
默認(rèn)類型策略具體實(shí)現(xiàn)


@Component
public class DefaultFileResolve implements IFileStrategy {

@Override
public FileTypeResolveEnum gainFileType() {
return FileTypeResolveEnum.File_DEFAULT_RESOLVE;
}

@Override
public void resolve(Object objectparam) {
logger.info("默認(rèn)類型解析文件,參數(shù):{}",objectparam);
//默認(rèn)類型解析具體邏輯
}
}

1.3.3 使用策略模式

如何使用呢?我們借助spring的生命周期,使用ApplicationContextAware接口,把對(duì)用的策略,初始化到map里面。然后對(duì)外提供resolveFile方法即可。


/**
*  @author 公眾號(hào):撿田螺的小男孩
*/
@Component
public class StrategyUseService implements ApplicationContextAware{


private Map iFileStrategyMap = new ConcurrentHashMap<>();

public void resolveFile(FileTypeResolveEnum fileTypeResolveEnum, Object objectParam) {
IFileStrategy iFileStrategy = iFileStrategyMap.get(fileTypeResolveEnum);
if (iFileStrategy != null) {
iFileStrategy.resolve(objectParam);
}
}

//把不同策略放到map
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);
tmepMap.values().forEach(strategyService -> iFileStrategyMap.put(strategyService.gainFileType(), strategyService));
}
}

2. 責(zé)任鏈模式

2.1 業(yè)務(wù)場(chǎng)景

我們來(lái)看一個(gè)常見(jiàn)的業(yè)務(wù)場(chǎng)景,下訂單。下訂單接口,基本的邏輯,一般有參數(shù)非空校驗(yàn)、安全校驗(yàn)、黑名單校驗(yàn)、規(guī)則攔截等等。很多伙伴會(huì)使用異常來(lái)實(shí)現(xiàn):


public class Order {

public void checkNullParam(Object param){
//參數(shù)非空校驗(yàn)
throw new RuntimeException();
}
public void checkSecurity(){
//安全校驗(yàn)
throw new RuntimeException();
}
public void checkBackList(){
//黑名單校驗(yàn)
throw new RuntimeException();
}
public void checkRule(){
//規(guī)則攔截
throw new RuntimeException();
}

public static void main(String[] args) {
Order order= new Order();
try{
order.checkNullParam();
order.checkSecurity ();
order.checkBackList();
order2.checkRule();
System.out.println("order success");
}catch (RuntimeException e){
System.out.println("order fail");
}
}
}

這段代碼使用了異常來(lái)做邏輯條件判斷,如果后續(xù)邏輯越來(lái)越復(fù)雜的話,會(huì)出現(xiàn)一些問(wèn)題:如異常只能返回異常信息,不能返回更多的字段,這時(shí)候需要自定義異常類。


并且,阿里開(kāi)發(fā)手冊(cè)規(guī)定:禁止用異常做邏輯判斷。


【強(qiáng)制】 異常不要用來(lái)做流程控制,條件控制。說(shuō)明:異常設(shè)計(jì)的初衷是解決程序運(yùn)行中的各種意外情況,且異常的處理效率比條件判斷方式要低很多。


如何優(yōu)化這段代碼呢?可以考慮責(zé)任鏈模式


2.2 責(zé)任鏈模式定義

當(dāng)你想要讓一個(gè)以上的對(duì)象有機(jī)會(huì)能夠處理某個(gè)請(qǐng)求的時(shí)候,就使用責(zé)任鏈模式。


責(zé)任鏈模式為請(qǐng)求創(chuàng)建了一個(gè)接收者對(duì)象的鏈。執(zhí)行鏈上有多個(gè)對(duì)象節(jié)點(diǎn),每個(gè)對(duì)象節(jié)點(diǎn)都有機(jī)會(huì)(條件匹配)處理請(qǐng)求事務(wù),如果某個(gè)對(duì)象節(jié)點(diǎn)處理完了,就可以根據(jù)實(shí)際業(yè)務(wù)需求傳遞給下一個(gè)節(jié)點(diǎn)繼續(xù)處理或者返回處理完畢。這種模式給予請(qǐng)求的類型,對(duì)請(qǐng)求的發(fā)送者和接收者進(jìn)行解耦。


責(zé)任鏈模式實(shí)際上是一種處理請(qǐng)求的模式,它讓多個(gè)處理器(對(duì)象節(jié)點(diǎn))都有機(jī)會(huì)處理該請(qǐng)求,直到其中某個(gè)處理成功為止。責(zé)任鏈模式把多個(gè)處理器串成鏈,然后讓請(qǐng)求在鏈上傳遞:


實(shí)戰(zhàn)!工作中常用到哪些設(shè)計(jì)模式責(zé)任鏈模式打個(gè)比喻:


假設(shè)你晚上去上選修課,為了可以走點(diǎn)走,坐到了最后一排。來(lái)到教室,發(fā)現(xiàn)前面坐了好幾個(gè)漂亮的小姐姐,于是你找張紙條,寫上:“你好, 可以做我的女朋友嗎?如果不愿意請(qǐng)向前傳”。紙條就一個(gè)接一個(gè)的傳上去了,后來(lái)傳到第一排的那個(gè)妹子手上,她把紙條交給老師,聽(tīng)說(shuō)老師40多歲未婚...


2.3 責(zé)任鏈模式使用

責(zé)任鏈模式怎么使用呢?


  • 一個(gè)接口或者抽象類
  • 每個(gè)對(duì)象差異化處理
  • 對(duì)象鏈(數(shù)組)初始化(連起來(lái))

2.3.1 一個(gè)接口或者抽象類

這個(gè)接口或者抽象類,需要:


  • 有一個(gè)指向責(zé)任下一個(gè)對(duì)象的屬性
  • 一個(gè)設(shè)置下一個(gè)對(duì)象的set方法
  • 給子類對(duì)象差異化實(shí)現(xiàn)的方法(如以下代碼的doFilter方法)
/**
*  關(guān)注公眾號(hào):撿田螺的小男孩
*/
public abstract class AbstractHandler {

//責(zé)任鏈中的下一個(gè)對(duì)象
private AbstractHandler nextHandler;

/**
* 責(zé)任鏈的下一個(gè)對(duì)象
*/
public void setNextHandler(AbstractHandler nextHandler){
this.nextHandler = nextHandler;
}

/**
* 具體參數(shù)攔截邏輯,給子類去實(shí)現(xiàn)
*/
public void filter(Request request, Response response) {
doFilter(request, response);
if (getNextHandler() != null) {
getNextHandler().filter(request, response);
}
}

public AbstractHandler getNextHandler() {
return nextHandler;
}

abstract void doFilter(Request filterRequest, Response response);

}

2.3.2 每個(gè)對(duì)象差異化處理

責(zé)任鏈上,每個(gè)對(duì)象的差異化處理,如本小節(jié)的業(yè)務(wù)場(chǎng)景,就有參數(shù)校驗(yàn)對(duì)象、安全校驗(yàn)對(duì)象、黑名單校驗(yàn)對(duì)象、規(guī)則攔截對(duì)象


/**
* 參數(shù)校驗(yàn)對(duì)象
**/
@Component
@Order(1) //順序排第1,最先校驗(yàn)
public class CheckParamFilterObject extends AbstractHandler {

@Override
public void doFilter(Request request, Response response) {
System.out.println("非空參數(shù)檢查");
}
}

/**
*  安全校驗(yàn)對(duì)象
*/
@Component
@Order(2) //校驗(yàn)順序排第2
public class CheckSecurityFilterObject extends AbstractHandler {

@Override
public void doFilter(Request request, Response response) {
//invoke Security check
System.out.println("安全調(diào)用校驗(yàn)");
}
}
/**
*  黑名單校驗(yàn)對(duì)象
*/
@Component
@Order(3) //校驗(yàn)順序排第3
public class CheckBlackFilterObject extends AbstractHandler {

@Override
public void doFilter(Request request, Response response) {
//invoke black list check
System.out.println("校驗(yàn)黑名單");
}
}

/**
*  規(guī)則攔截對(duì)象
*/
@Component
@Order(4) //校驗(yàn)順序排第4
public class CheckRuleFilterObject extends AbstractHandler {

@Override
public void doFilter(Request request, Response response) {
//check rule
System.out.println("check rule");
}
}


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉