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

你看那代碼,好像一條鏈哎

開(kāi)發(fā) 前端
就如星爺多年前說(shuō)的那樣“你看那代碼,好像一條鏈哎”。什么?他沒(méi)說(shuō)過(guò)嗎,或許我記錯(cuò)了。你應(yīng)該已經(jīng)猜到了,這篇文章,我們來(lái)討論一下責(zé)任鏈設(shè)計(jì)模式。這個(gè)模式并不流行,至少在 Gang of Four定義的模式中是這樣。但現(xiàn)代依賴注入框架讓我們可以用巧妙的新奇的方式去實(shí)現(xiàn)這個(gè)模式,我們來(lái)看看。

就如星爺多年前說(shuō)的那樣“你看那代碼,好像一條鏈哎”。什么?他沒(méi)說(shuō)過(guò)嗎,或許我記錯(cuò)了。你應(yīng)該已經(jīng)猜到了,這篇文章,我們來(lái)討論一下責(zé)任鏈設(shè)計(jì)模式。這個(gè)模式并不流行,至少在 Gang of Four定義的模式中是這樣。但現(xiàn)代依賴注入框架讓我們可以用巧妙的新奇的方式去實(shí)現(xiàn)這個(gè)模式,我們來(lái)看看。

介紹

聲明:這種模式并沒(méi)有新東西。我的一個(gè)同事剛剛前幾天使用過(guò),我也曾用過(guò)很多次。這篇文章的靈感來(lái)源于我最近遇到的問(wèn)題,我們下面來(lái)說(shuō)說(shuō),我之前也沒(méi)有意識(shí)到這個(gè)問(wèn)題可以用這種模式來(lái)解決。

傳統(tǒng)模式

責(zé)任鏈模式是一種行為設(shè)計(jì)模式,它***在Gang of Four寫(xiě)的Design Patterns這本書(shū)中提及。模式的目的是:

避免請(qǐng)求的發(fā)送者與接收者耦合,為多個(gè)對(duì)象提供處理請(qǐng)求的機(jī)會(huì).將接收對(duì)象串聯(lián)成鏈,請(qǐng)求在鏈上傳遞,直到被一個(gè)對(duì)象處理.

類(lèi)的關(guān)系圖如下所示:

通過(guò)定義一個(gè)可以用來(lái)響應(yīng)客戶端請(qǐng)求的標(biāo)準(zhǔn)接口,來(lái)實(shí)現(xiàn)松耦合。在上面的圖中,表現(xiàn)為Handler抽象類(lèi)型??梢酝ㄟ^(guò)創(chuàng)建鏈?zhǔn)降念?lèi),繼承上面的接口來(lái)實(shí)現(xiàn)多個(gè)類(lèi)響應(yīng)請(qǐng)求的能力。每一個(gè)類(lèi)在鏈中擁有下一個(gè)節(jié)點(diǎn)的實(shí)例。successor屬性滿足作用域。

當(dāng)調(diào)用時(shí),每一個(gè)handler確定自己是否有能力處理請(qǐng)求。如果有,它執(zhí)行請(qǐng)求的操作,在這,我們可以根據(jù)請(qǐng)求的轉(zhuǎn)發(fā)規(guī)則實(shí)現(xiàn)許多不同的處理方式。一旦一個(gè)ConcreteHandler聲明可以處理這個(gè)請(qǐng)求,我們可以實(shí)現(xiàn)規(guī)則用于停止請(qǐng)求在鏈中傳遞。這種情況下,handleRequest方法的實(shí)現(xiàn)方式如下所示:

if (/* The request can be successfully handled */) {
    // Handle the request
} else {
    successor.handleRequest(request);
}

另一方面,我們可以將請(qǐng)求轉(zhuǎn)發(fā)到鏈中的下一個(gè)handler,無(wú)論當(dāng)前的handler是否能處理。

if (/* The request can be successfully handled */) {
    // Handle the request
}
successor.handleRequest(request);

構(gòu)建鏈的操作應(yīng)該和下面差不多。

Handler chain = new ConcreteHandler1(new ConcreteHandler2(new ConcreteHandler3()));
chain.handleRequest(request);

在JDK內(nèi)部實(shí)現(xiàn)中,至少有兩個(gè)地方用到了這種模式:

  • logging機(jī)制的實(shí)現(xiàn):java.util.logging.Logger#log()
  • http請(qǐng)求過(guò)濾器機(jī)制和Servlet響應(yīng)規(guī)范的實(shí)現(xiàn):javax.servlet.Filter#doFilter()

依賴注入的出現(xiàn)

正如許多其他的情況一樣,依賴注入模式的出現(xiàn)改變了一切。讓我們看看依賴注入特性如何使責(zé)任鏈模式現(xiàn)代化。

首先,我們需要一個(gè)所有依賴注入庫(kù)都實(shí)現(xiàn)的特性:multibindings?;旧希梢蕴峁┮粋€(gè)類(lèi)型的所有子類(lèi)型的實(shí)例,僅僅通過(guò)注入這個(gè)類(lèi)型的集合。

比如下面這個(gè)類(lèi)型系統(tǒng):

interface Shop {}
class PetShop implements Shop {}
class Grocery implements Shop {}
class Drugstore implements Shop {}
// And so on...

現(xiàn)在,我們定義一個(gè)新類(lèi)型ShoppingCenter,它擁有Shop每個(gè)子類(lèi)型的實(shí)例。使用依賴注入,我們可以通過(guò)在ShoppingCenter注入一個(gè)Shop集合來(lái)實(shí)現(xiàn)這一目標(biāo)。

class ShoppingCenter {
    private final Set<Shop> shops;
    @Inject
    public void ShoppingCenter(Set<Shop> shops) {
        this.shops = shops;
    }
    // Class body using shops
}

真TM簡(jiǎn)單!顯然,每一個(gè)依賴注入庫(kù)都有自己的配置來(lái)解決這種情況。在Spring中,使用auto-discovery特性,你只需要一點(diǎn)小小的配置。在Guice,稍稍復(fù)雜,但最終結(jié)果一樣。

責(zé)任鏈模式的現(xiàn)代化實(shí)現(xiàn)

簡(jiǎn)單總結(jié)一下:我們已經(jīng)看到了責(zé)任鏈模式的典型形式;我們看到了依賴注入庫(kù)提供的multibinding特性;***,我們看到了如何把這兩個(gè)概念搭配使用。

首先,我們需要一個(gè)與原始的責(zé)任鏈設(shè)計(jì)模式稍有不同的實(shí)現(xiàn)。讓我們引入一個(gè)新的類(lèi)型ChainHandler。這個(gè)類(lèi)型的職責(zé)就是擁有整個(gè)鏈,并暴露出一個(gè)接口,用于訪問(wèn)鏈提供給客戶端的操作函數(shù)。

class ChainHandler {
    private final Set<Handler> handlers;
    @Inject
    public void ChainHandler(Set<Handler> handlers) {
        this.handlers = handlers;
    }
    // Pass the request to each handler of the chain
    public void handle(final Request request) {
        handlers.forEach(h -> h.handle(request));
    }
}

利用依賴注入的優(yōu)勢(shì),在不改變已有代碼的基礎(chǔ)上增加一個(gè)Handler的實(shí)現(xiàn)。這意味著實(shí)際上我們不需要執(zhí)行回歸測(cè)試。另一方面,將Handler的執(zhí)行放入鏈中有一點(diǎn)困難(但并不是不能)

警告

正如很多其他的模式一樣,專注于構(gòu)造模式的每個(gè)類(lèi)的角色是什么很重要。你會(huì)給每個(gè)具體的Handler什么功能?你會(huì)把應(yīng)用的業(yè)務(wù)邏輯直接放在Handler里面嗎?

首先,我們很多人都會(huì)提供上面的解決方案,這并不完全錯(cuò)誤。然而,這種設(shè)計(jì)限制了代碼的復(fù)用并違反了單一職責(zé)原則(Single Responsibility Principle)。

舉個(gè)例子,我們需要實(shí)現(xiàn)一個(gè)系統(tǒng),用來(lái)在金融業(yè)務(wù)中補(bǔ)全信息,補(bǔ)全操作使用責(zé)任鏈模式。一個(gè)可能要插入的補(bǔ)全信息就是根據(jù)IBAN(國(guó)際銀行賬號(hào))或BIC碼(銀行代碼)導(dǎo)出的收款人國(guó)家。然后我們來(lái)定義一個(gè)CountryPayeeEnricher。

首先看一下,我們可以在CountryPayeeEnricher中直接編寫(xiě)代碼用來(lái)補(bǔ)全國(guó)家信息。但如果我們需要在我們應(yīng)用的其他位置(或其他應(yīng)用)復(fù)用這個(gè)功能呢?遵循組合原則是一個(gè)更好地解決方案,將代碼放進(jìn)一個(gè)專有的類(lèi)中,比如PayeeService:

class PayeeService {
    public Country deriveCountryFromPayee(String payee) {
        // Code that extract the country information from the
        // input payess
    }
    // Omissis...
}
class CountryPayeeEnricher implements Enrichment {
    private PayeeService payeeService;
    @Inject
    public void CountryPayeeEnricher(PayeeService payeeService) {
        this.payeeService = payeeService;
    }
    public void handle(Transaction tx) {
        Country country = payeeService.deriveCountryFromPayee(tx.getPayee());
        tx.setCountry(country);
        // ...or something like this
    }
}

通過(guò)這種方式,我們最終有了兩個(gè)擁有不同職責(zé)的類(lèi)型:PayeeService類(lèi)型,提供可復(fù)用的直接聯(lián)系收款人信息的服務(wù)。CountryPayeeEnricher類(lèi)型,代替之前類(lèi)型提供服務(wù)的標(biāo)準(zhǔn)入口。

Scala方式

為了***,我也想討論一下用Scala語(yǔ)言實(shí)現(xiàn)責(zé)任鏈模式。正如很多其他設(shè)計(jì)模式一樣,這門(mén)語(yǔ)言內(nèi)部已經(jīng)實(shí)現(xiàn)了責(zé)任鏈模式:偏函數(shù)(partial functions)。在理論層面,偏函數(shù)是定義了域里的一部分值的函數(shù)。在Scala中,這種函數(shù)有一個(gè)特別的類(lèi)型——PartialFunction[T, V]

在Scala中使用模式匹配(pattern matching)聲明來(lái)定義偏函數(shù),在下面這個(gè)例子中,fraction的默認(rèn)值是0。

val fraction: PartialFunction[Int, Int] = {
  case d: Int if d != 0 =>  42 / d
}

如果有多個(gè)定義集合,你可以有多個(gè)case子句。如果你為了應(yīng)用函數(shù),把每個(gè)case子句作為滿足的情況(責(zé)任鏈里的handler,記得嗎?),你就再次用到了責(zé)任鏈:

case class Request(val value: String) { /* ... */ }
val someStupidFunction: PartialFunction[Request, String] = {
  case Request(42) => "The final answer"
  case Request(0) => "You know nothing, John Snow"
  case Request(666) => "Something strange is going on in here"
  //. ..
}

緊接著,一個(gè)偏函數(shù)可以當(dāng)做好多handler構(gòu)成的鏈。顯然,通過(guò)這種方式使用責(zé)任鏈模式,你必須遵守一些額外的約束。事實(shí)上:

  • 你不能在每個(gè)handler中儲(chǔ)存元數(shù)據(jù)
  • 你不能從鏈中移除handler
  • 你不能顯示檢查handler或美觀的打印它

如果你確實(shí)不需要做上面這些事情,模式匹配偏函數(shù)(pattern-matching PartialFunctions)用起來(lái)相當(dāng)棒。

責(zé)任編輯:張燕妮 來(lái)源: 碼農(nóng)網(wǎng)
相關(guān)推薦

2018-03-29 02:29:27

2021-05-25 09:59:50

前端開(kāi)發(fā)工具

2013-08-29 09:48:29

云計(jì)算部署云部署云退出策略

2024-02-01 18:07:37

2012-11-30 11:26:00

代碼注釋

2010-04-13 16:57:01

2020-05-25 09:00:35

郭德綱程序員互聯(lián)網(wǎng)

2021-08-03 08:41:18

SQLMysql面試

2023-07-28 22:27:41

PromptGPT

2019-03-28 10:09:49

內(nèi)存CPU硬盤(pán)

2011-03-21 17:19:12

LAMPUbuntu

2025-05-20 00:00:00

2025-10-16 07:05:00

SparkSQLSpark 內(nèi)核

2011-12-29 20:58:46

Windows Pho

2011-05-12 14:43:57

MYSQL

2025-06-04 08:20:30

2021-04-16 07:04:53

SQLOracle故障

2011-06-24 09:20:04

編程語(yǔ)言

2017-10-21 10:37:28

2020-07-03 07:39:45

查詢語(yǔ)句
點(diǎn)贊
收藏

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