職責鏈模式

2021-07-29 11:26:13 字數 4438 閱讀 2521

很多情況下,在乙個軟體系統中可以處理某個請求的物件不止乙個,例如scm系統中的採購單審批,主任、副董事長、董事長和董事會都可以處理採購單,他們可以構成一條處理採購單的鏈式結構,採購單沿著這條鏈進行傳遞,這條鏈就稱為職責鏈。職責鏈可以是一條直線、乙個環或者乙個樹形結構,最常見的職責鏈是直線型,即沿著一條單向的鏈來傳遞請求。鏈上的每乙個物件都是請求處理者,職責鏈模式可以將請求的處理者組織成一條鏈,並讓請求沿著鏈來傳遞,由鏈上的處理者對請求進行相應的處理,客戶端無須關心請求的處理細節以及請求的傳遞,只需將請求傳送到鏈上即可,實現請求傳送者和請求處理者解耦。

職責鏈模式(chain of responsibility pattern):避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,並且沿著這條鏈傳遞請求,知道有物件處理為止。職責鏈模式是一種物件行為型模式。

在職責鏈模式結構圖中包含如下幾個角色:

在職責鏈模式裡,很多物件由每乙個物件對其下家的引用而連線起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某乙個物件決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪乙個物件最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。

職責鏈模式的核心在於抽象處理者類的設計,抽象處理者的典型**如下所示:

abstract class handler 

public

abstract

void

handlerequest(string request);

}

上述**中,抽象處理者類定義了對下家的引用物件,以便將請求**給下家,該物件的訪問符可設為protected,在其子類中可以使用。在抽象處理者類中宣告了抽象的請求處理方法,具體實現交由子類完成。

具體處理者是抽象處理者的子類,它具有兩大作用:第一是處理請求,不同的具體處理者以不同的形式實現抽象請求處理方法handlerequest();第二是**請求,如果該請求超出了當前處理者類的許可權,可以將該請求**給下家。具體處理者類的典型**如下:

class concretehandler extends handler else }}

在具體處理類中通過對請求進行判斷可以做出相應的處理。

需要注意的是,職責鏈模式並不建立職責鏈,職責鏈的建立工作必須由系統的其他部分來完成,一般是在使用該職責鏈的客戶端中建立職責鏈。職責鏈模式降低了請求的傳送端和接收端之間的耦合,使多個物件都有機會處理這個請求。

sunny軟體公司承接了某企業scm(supply chain management **鏈管理)系統的開發任務,其中包含乙個採購審批子系統。該企業的採購審批是分級進行的,即根據採購金額的不同由不同層次的主管人員來審批,主任可以審批5萬元以下(不包括5萬元)的採購單,副董事長可以審批5萬元至10萬元(不包括10萬元)的採購單,董事長可以審批10萬元至50萬元(不包括)的採購單50萬元及以上的採購單就需要開董事會討論決定。

為了讓採購單的審批流程更加靈活,並實現採購單的鏈式傳遞和處理,sunny公司開發人員使用職責鏈模式來實現採購單的分級審批,其基本結構如下圖所示:

工程目錄結構

採購單:請求類

package cn.red.responsibility.chain;

public

class

purchaserequest

public

double

getamount()

public

void

setamount(double amount)

public

intgetnumber()

public

void

setnumber(int number)

public string getpurpose()

public

void

setpurpose(string purpose)

}

審批者類:抽象處理者

package cn.red.responsibility.chain;

public

abstract

class

// 定義後繼物件

// 審批者姓名

protected string name;

public

super();

this.name = name;

}//設定後繼者

public

void

this.successor = successor;

}//抽象請求處理方法

public

abstract

void

processrequest(purchaserequest request);

}

主任類:具體處理者

package cn.red.responsibility.chain;

public

class

director

extends

public

director(string name)

@override

public

void

processrequest(purchaserequest request) else }}

副董事長類:具體處理者

package cn.red.responsibility.chain;

public

class

vicepresident

extends

public

vicepresident(string name)

@override

public

void

processrequest(purchaserequest request) else }}

董事長類:具體處理者

package cn.red.responsibility.chain;

public

class

president

extends

public

president(string name)

@override

public

void

processrequest(purchaserequest request) else }}

董事會類:具體處理者

package cn.red.responsibility.chain;

public

class

congress

extends

public

congress(string name)

@override

public

void

processrequest(purchaserequest request)

}

客戶端測試**

package cn.red.responsibility.chain;

public

class

client

}

輸出結果

主任傑克審批採購單:45000.0

副董事長傑瑞審批採購單:60000.0

董事長肉絲審批採購單:160000.0

董事會審批採購單:800000.0

職責鏈模式通過建立一條鏈來組織請求的處理者,請求將沿著鏈進行傳遞,請求傳送者無須知道請求在何時、何處以及如何被處理,實現了請求傳送者與處理者的解耦。在軟體開發中,如果遇到有多個物件可以處理同一請求時可以應用職責鏈模式,例如在web應用開發中建立乙個過濾器(filter)鏈來對請求資料進行過濾,在工作流系統中實現公文的分級審批等等,使用職責鏈模式可以較好地解決此類問題。1.主要優點

2.主要缺點

(1)有多個物件可以處理同乙個請求,具體哪個物件處理該請求待執行時刻再確定,客戶端只需將請求提交到鏈上,而無須關心請求的處理物件是誰以及它是如何處理的。

(2)在不明確指定接收者的情況下,向多個物件中乙個提交乙個請求。

(3)可動態指定一組物件處理請求,客戶端可以動態建立職責鏈來處理請求,還可以改變鏈中處理者之間的先後次序。

職責鏈模式

1.職責鏈 namespace dutychainpattern 用來處理請求 public abstract void transmitrequest int request 班主任 職責鏈上的乙個節點,在裡面進行判斷,看能否處理請求,不能則將請求轉移 public class classadvi...

職責鏈模式

軟體領域中的設計模式為開發人員提供了一種使用專家設計經驗的有效途徑。設計模式中運用了物件導向程式設計語言的重要特性 封裝 繼承 多型,真正領悟設計模式的精髓是可能乙個漫長的過程,需要大量實踐經驗的積累。最近看設計模式的書,對於每個模式,用c 寫了個小例子,加深一下理解。主要參考 大話設計模式 和 設...

職責鏈模式

劇情簡要 學習此模式,讓筆者聯想到自然界的生物鏈。打個比方 大魚吃小魚,小魚吃蝦公尺。河裡的小蝦公尺問大魚,你要不要吃我啊?大魚說 你太小了,吃了 沒吃,return 懶得吃!然後蝦公尺又問小魚 小螃蟹 小河馬同樣的問題。其實如果小蝦公尺這麼想自我了結的話,根本不用這麼費勁。這就開始了我們職責鏈模式...