偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

徹底搞懂策略設(shè)計(jì)模式

開發(fā) 前端
什么是策略呢?所謂策略,你可以理解它就是?一組算法或?qū)崿F(xiàn)方法的組合。我們知道,實(shí)現(xiàn)某個(gè)功能的方法可能有很多。如果我們把這些方法封裝起來,并能夠確保它們可以相互替換,那么就可以構(gòu)建出一系列的實(shí)現(xiàn)策略,這就是策略模式的由來。

對(duì)于任何一個(gè)軟件系統(tǒng)而言,從組成結(jié)構(gòu)上通常可以分成兩大部分,內(nèi)核組件和擴(kuò)展組件。我們知道,內(nèi)核組件是需要非常穩(wěn)定的,而擴(kuò)展組件則應(yīng)該按需開發(fā),動(dòng)態(tài)替換。

內(nèi)核和擴(kuò)展結(jié)構(gòu)示意圖內(nèi)核和擴(kuò)展結(jié)構(gòu)示意圖

顯然,想要實(shí)現(xiàn)這張圖中的效果,我們需要對(duì)擴(kuò)展組件進(jìn)行抽象。

基于這種抽象,就可以實(shí)現(xiàn)不同的擴(kuò)展組件。而因?yàn)檫@些擴(kuò)展組件都是抽象組件的具體實(shí)現(xiàn),所以它們可以相互替換。

抽象組件和擴(kuò)展組件之間的關(guān)系抽象組件和擴(kuò)展組件之間的關(guān)系

其實(shí)想要實(shí)現(xiàn)圖中的這種效果,我們有很多種方法。在面向?qū)ο蟮氖澜缰?,我們可以引入一種專門的設(shè)計(jì)模式來做到這一點(diǎn),這種設(shè)計(jì)模式就是我們今天要講的策略模式。

策略模式的基本概念和簡單示例

那么,什么是策略呢?所謂策略,你可以理解它就是 一組算法或?qū)崿F(xiàn)方法的組合。我們知道,實(shí)現(xiàn)某個(gè)功能的方法可能有很多。如果我們把這些方法封裝起來,并能夠確保它們可以相互替換,那么就可以構(gòu)建出一系列的實(shí)現(xiàn)策略,這就是策略模式的由來。這個(gè)模式的結(jié)構(gòu)可以這樣表示:

策略模式的結(jié)構(gòu)示意圖策略模式的結(jié)構(gòu)示意圖

這張圖中,可以看到,Strategy 是一個(gè)公共接口,代表對(duì)具體實(shí)現(xiàn)方法的抽象。而 ConcreteStrategyA 和 ConcreteStrategyB 分別是 Strategy 接口的兩個(gè)實(shí)現(xiàn)類,代表了不同的實(shí)現(xiàn)方法。同時(shí),我們還注意到,這里有一個(gè)上下文組件 Context,來保持對(duì) Strategy 接口的引用。

顯然,我們可以把這里的 Context 看作是內(nèi)核組件,而 Strategy 接口以及兩個(gè) ConcreteStrategy 實(shí)現(xiàn)類分別看作抽象組件和擴(kuò)展組件。

前面已經(jīng)提到,在面向?qū)ο蟮氖澜缰?,我們通常使用接口來定義一種策略。例如,在這個(gè) Strategy 接口中,我們定義了一個(gè)方法,這個(gè)方法可以用來對(duì)輸入的兩個(gè)數(shù)字執(zhí)行某一個(gè)操作。

public interface Strategy {
   public int execute(int num1, int num2);
}

然后,我們就可以基于這個(gè) Strategy 接口,來實(shí)現(xiàn)對(duì)這兩個(gè)數(shù)字的具體計(jì)算方法。這里列舉了常見的加法、減法和乘法。

public class AdditionStrategy implements Strategy{
   @Override
   public int execute(int num1, int num2) {
      return num1+ num2;
   }
}
publicclass SubtractionStrategy implements Strategy{
   @Override
   public int execute(int num1, int num2) {
      return num1- num2;
   }
}
publicclass MultiplicationStrategy implements Strategy{
   @Override
   public int execute(int num1, int num2) {
      return num1* num2;
   }
}

這些算法都非常簡單,而對(duì)應(yīng)的 Context 類也并不復(fù)雜。我們?cè)谶@個(gè)類中注入了一個(gè) Strategy 接口,然后通過這個(gè)接口的 execute 方法,來執(zhí)行具體的計(jì)算方法。

public class Context {
   private Strategy strategy;
   public Context(Strategy strategy){
      this.strategy = strategy;
   }
   public int performCalculation(int num1, int num2){
      return strategy.execute(num1, num2);
   }
}

針對(duì)上面 Context,我們也可以編寫對(duì)應(yīng)的測(cè)試類。

public class StrategyTest {
   public static void main(String[] args) {
      Context context1= new Context(new AdditionStrategy());
      System.out.println(context.executeStrategy(1, 1));
      Context context2 = new Context(new SubtractionStrategy());
      System.out.println( context.executeStrategy(1, 1));
      Context context3 = new Context(new MultiplicationStrategy());
      System.out.println(context3.executeStrategy(1, 1));
   }
}

顯然,策略模式本身的實(shí)現(xiàn)方式非常清晰。但在日常開發(fā)過程中,我們很少碰到像上面的代碼示例這樣簡單的應(yīng)用場(chǎng)景。這時(shí)候,就需要我們理解策略模式的本質(zhì)作用,從繁冗復(fù)雜的代碼結(jié)構(gòu)中識(shí)別出策略模式的應(yīng)用方式,從而更好地把握代碼的結(jié)構(gòu)。

策略模式在主流開源框架中可以說應(yīng)用非常廣泛。接下來,我們就以 MyBatis 框架為例,來分析一下它的應(yīng)用場(chǎng)景和實(shí)現(xiàn)過程。

策略模式在 MyBatis 中的應(yīng)用與實(shí)現(xiàn)

在 MyBatis 中,策略模式的應(yīng)用場(chǎng)景主要就在 SQL 的執(zhí)行器組件——Executor 中。作為 MyBatis 中最核心的接口之一,Executor 接口定義的內(nèi)容非常豐富,這里列舉幾個(gè)比較有代表性的方法:

public interface Executor {
//執(zhí)行 update、insert、delete 三種類型的 SQL 語句
int update(MappedStatement ms, Object parameter) throws SQLException;
//執(zhí)行 selete 類型的 SQL 語句,返回值分為結(jié)果對(duì)象列表或游標(biāo)對(duì)象
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
 ...
//批量執(zhí)行 SQL 語句
List<BatchResult> flushStatements() throws SQLException;
//提交事務(wù)
void commit(boolean required) throws SQLException;
//回滾事務(wù)
void rollback(boolean required) throws SQLException;
}

在上面代碼中,我們看到了一組用來實(shí)現(xiàn)數(shù)據(jù)庫訪問的常用方法,包括用于執(zhí)行查詢的 query 方法、用于執(zhí)行更新的 update 方法、用于提交和回滾事務(wù)的 commit 和 rollback 方法,以及用于執(zhí)行批量 SQL 的 flushStatements 方法。

在 MyBatis 中,Executor 接口具有一批實(shí)現(xiàn)類。

MyBatis 中 Executor 接口的類層結(jié)構(gòu)圖MyBatis 中 Executor 接口的類層結(jié)構(gòu)圖

  • SimpleExecutor:普通執(zhí)行器
    這是 MyBatis 中最基礎(chǔ)的、也是默認(rèn)使用的一種 Executor,封裝了對(duì)基本 SQL 語句的各種操作。
  • ReuseExecutor:重用執(zhí)行器
    顧名思義,這種 Executor 提供了對(duì) SQL 語句進(jìn)行重復(fù)利用的功能特性。基于這種功能特性,SQL 語句的創(chuàng)建、銷毀以及預(yù)編譯過程會(huì)得到優(yōu)化,從而降低資源消耗,提高性能。
  • BatchExecutor:批處理執(zhí)行器
    從命名上,我們也不難看出,這種 Executor 的作用就是完成對(duì) SQL 語句的批量處理。批處理的優(yōu)勢(shì)同樣是節(jié)省資源消耗,因?yàn)槲覀兛梢砸淮蜗驍?shù)據(jù)庫發(fā)送多條 SQL 語句。

顯然,這三個(gè) Executor 實(shí)現(xiàn)類就是對(duì) Executor 的不同策略實(shí)現(xiàn)。明確了這一點(diǎn)之后,我們接下來還需要明確兩個(gè)問題,也就是:

  • 這些具體策略實(shí)現(xiàn)類是如何生成的呢?
  • 在 MyBatis 中,哪個(gè)組件扮演了 Context 角色呢?

我們先來看第一個(gè)問題。在 MyBatis 的配置文件中存在一個(gè)配置項(xiàng),這個(gè)配置項(xiàng)用于設(shè)置 Executor 的默認(rèn)類型。正如上面所討論的,這個(gè)配置項(xiàng)指定了 MyBatis 默認(rèn)采用的 Executor 是 SimpleExecutor。

<setting name="defaultExecutorType" value="SIMPLE" />

那么,Executor 是從哪里創(chuàng)建出來的呢?這就涉及到 MyBatis 中與配置相關(guān)的 Configuration 類。Configuration 是一種門面類,但也扮演著工廠類的角色,能夠根據(jù)傳入的策略類型來生成具體的策略對(duì)象。

protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
public Executor newExecutor(Transaction transaction) {
    return newExecutor(transaction, defaultExecutorType);
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } elseif (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    ...
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
}

可以看到,這里通過 Executor 的類型——ExecutorType,來決定構(gòu)建哪一種具體的 Executor 實(shí)現(xiàn)類。請(qǐng)注意,我們?cè)谶@里看到了一個(gè) interceptorChain 對(duì)象,這是 MyBatis 中的攔截器組件,體現(xiàn)的是一種責(zé)任鏈處理機(jī)制。

接下來,我們討論第二個(gè)問題,就是在 MyBatis 中,哪個(gè)組件扮演了 Context 角色呢?答案是 DefaultSqlSession。

DefaultSqlSession 內(nèi)部包含了對(duì) Executor 的引用,而 DefaultSqlSession 是通過 SqlSessionFactory 接口的默認(rèn)實(shí)現(xiàn)類——DefaultSqlSessionFactory 進(jìn)行構(gòu)建的。在 SqlSession 生成過程中,需要指定 ExecutorType。這時(shí)就會(huì)調(diào)用 Configuration 對(duì)象的這個(gè) newExecutor 方法。

DefaultSqlSession 相關(guān)類層結(jié)構(gòu)圖DefaultSqlSession 相關(guān)類層結(jié)構(gòu)圖

在具體實(shí)現(xiàn)過程中,策略模式也可以和其他設(shè)計(jì)模式組合在一起使用。例如,MyBatis 針對(duì) Executor 的設(shè)計(jì),同時(shí)使用了模板方法模式和策略模式。來看一下整合了模板方法模式和策略模式的類層結(jié)構(gòu)圖。

Executor 接口完整類層結(jié)構(gòu)圖Executor 接口完整類層結(jié)構(gòu)圖

總的來說,針對(duì) SQL 執(zhí)行過程,我們知道 MyBatis 分別提供了 SimpleExecutor、ReuseExecutor 以及 BatchExecutor 這三種不同的實(shí)現(xiàn)策略。這三種 Executor 都有一個(gè)共同的父類——BaseExecutor,在這個(gè)類中定義了一組抽象方法,交由它的三個(gè)子類進(jìn)行實(shí)現(xiàn),這種實(shí)現(xiàn)方式就是典型的模板方法設(shè)計(jì)模式。實(shí)際工作中,策略模式和模板方法模式也是一種常見的組合模式。

總結(jié)

最后我來給你總結(jié)一下。

圖片圖片

如果你正在考慮圍繞一個(gè)業(yè)務(wù)場(chǎng)景提供不同的實(shí)現(xiàn)方法,那么可以先停下來,分析一下業(yè)務(wù)場(chǎng)景是否可以使用策略模式進(jìn)行實(shí)現(xiàn)。如果這些不同的實(shí)現(xiàn)方法體現(xiàn)的是算法之間的區(qū)別,而不是執(zhí)行流程上的差異,我們就可以引入今天所介紹的策略模式,并對(duì)其進(jìn)行設(shè)計(jì)。策略模式是一種非常有用的設(shè)計(jì)模式,我們也通過基本的實(shí)現(xiàn)代碼示例給出了它的實(shí)現(xiàn)方法。

就實(shí)現(xiàn)方法而言,采用策略模式的第一步,是設(shè)計(jì)一個(gè)合理的策略接口。然后基于不同算法,為這個(gè)接口提供不同的實(shí)現(xiàn)類。一旦構(gòu)建了多個(gè)實(shí)現(xiàn)類之后,我們就可以針對(duì)具體場(chǎng)景,選擇具體的實(shí)現(xiàn)類,或者提供新的實(shí)現(xiàn)類。策略模式能確保這些實(shí)現(xiàn)類之間相互獨(dú)立,并可以做到靈活替換。

責(zé)任編輯:武曉燕 來源: 程序員技術(shù)充電站
相關(guān)推薦

2024-01-29 12:22:07

設(shè)計(jì)模式策略模式

2023-05-22 13:27:17

2025-04-21 00:50:50

2020-07-02 09:15:59

Netty內(nèi)存RPC

2013-11-26 16:09:34

Android設(shè)計(jì)模式

2021-06-09 08:53:34

設(shè)計(jì)模式策略模式工廠模式

2015-09-08 13:39:10

JavaScript設(shè)計(jì)模式

2024-02-26 11:52:38

代理模式設(shè)計(jì)

2024-02-19 13:11:38

門面模式系統(tǒng)

2025-04-21 04:00:00

2024-02-21 12:24:33

模板設(shè)計(jì)模式框架

2024-01-30 13:15:00

設(shè)計(jì)模式責(zé)任鏈

2024-02-23 12:11:53

裝飾器模式對(duì)象

2024-10-06 12:56:36

Golang策略設(shè)計(jì)模式

2017-07-07 10:55:14

數(shù)據(jù)庫MongoDB設(shè)計(jì)模式

2024-02-04 12:04:17

2024-02-27 11:59:12

享元模式對(duì)象

2017-12-05 17:44:31

機(jī)器學(xué)習(xí)CNN卷積層

2020-10-14 08:50:38

搞懂 Netty 線程

2025-05-06 01:14:00

系統(tǒng)編程響應(yīng)式
點(diǎn)贊
收藏

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