Iron之职责链
需求:
"Iron"的建造一直没有停止,现在单个部件是有的,但是在部件从工厂里出来的时候,在组装到一起之前,我们还是非常有必要对部件进行质量检测,或者是其它个方面的检测,又或者是设置部件标识信息等等,这些操作可以是有序的(也可以是无序的)。
现在为了实现上面的所讲的功能来进行演示,然过程中会发现问题,然后解决问题。这里不多说了直接进入主题。
问题的发现:
首先我定义了一个ComponentModel类,它是要被检验的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
1
/// <summary>
2
/// 部件
3
/// </summary>
4
public
class
ComponentModel
5 {
6
public
string
Name {
get
;
set
; }
7
public
int
Value
8 {
9
get
10 {
11
return
5;
12 }
13 }
14 }
|
这里先定义了一个请求处理类型的枚举,下面要用到,这样比用什么字符串或者是数字来作条件判断要好很多。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
1
/// <summary>
2
/// 请求的处理类型
3
/// </summary>
4
public
enum
RequestState
5 {
6
/// <summary>
7
/// 检测
8
/// </summary>
9 Check,
10
/// <summary>
11
/// 设置基础值
12
/// </summary>
13 SetDefValue
14
15 }
|
再然后,我们再来定义检验ComponentModel类的类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
1
/// <summary>
2
/// 处理请求类1
3
/// </summary>
4
public
class
ConcreteHandlerCaseOne
5 {
6
private
ComponentModel _comModel;
7
public
ConcreteHandlerCaseOne(ComponentModel comModel)
8 {
9 _comModel = comModel;
10 }
11
public
void
HandleRequest(RequestState reqState)
12 {
13
switch
(reqState)
14 {
15
case
RequestState.Check:
16
if
(_comModel.Value > 5)
17 {
18
//执行处理
19 }
20
break
;
21
case
RequestState.SetDefValue:
22 _comModel.Name =
"默认部件"
;
23
//执行处理
24
break
;
25
default
:
26
27
break
;
28 }
30 }
31 }
32
/// <summary>
33
/// 处理请求类2
34
/// </summary>
35
public
class
ConcreteHandlerCaseTwo
36 {
37
private
ComponentModel _comModel;
38
public
ConcreteHandlerCaseTwo(ComponentModel comModel)
39 {
40 _comModel = comModel;
41 }
42
public
void
HandleRequest(RequestState reqState)
43 {
44
switch
(reqState)
45 {
46
case
RequestState.Check:
47
if
(_comModel.Value > 5)
48 {
49
//执行处理
50 }
51
break
;
52
case
RequestState.SetDefValue:
53 _comModel.Name =
"默认部件"
;
54
//执行处理
55
break
;
56
default
:
57
58
break
;
59
60 }
61 }
62 }
|
定义了两个类型,ConcreteHandlerCaseOne和ConcreteHandlerCaseTwo两个类型,都是用来处理检测ComponentModel类型的,现在这些类型都齐全了我们来检测一下吧。
1
2
3
4
5
|
1 ComponentModel comModel =
new
ComponentModel();
2 ConcreteHandlerCaseOne caseone =
new
ConcreteHandlerCaseOn(comModel);
3 caseone.HandleRequest(RequestState.Check);
4 ConcreteHandlerCaseTwo casetwo =
new
ConcreteHandlerCaseTw(comModel);
5 casetwo.HandleRequest(RequestState.Check);
|
对的,就是这样,一次次的检测下去,如果要检测20次,并且都是不同的实现,那将非常可怕,代码冗余,而且请求调用方和处理方的耦合度也很大,那要怎么样让代码更精简,并且还能有效的解耦,这里就要用到职责链模式。
为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
——Gof
这里要强调一下的是本篇的示例中并没有完全遵从设计模式的定义,还是按照本文开始的功能需求来做的设计,当然了模式的核心不变。
设计模式的思想:
现在先对处理方进行抽象:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1
/// <summary>
2
/// 抽象处理者
3
/// </summary>
4
public
abstract
class
Handle
5 {
6
protected
Handle Successor;
7
public
void
SetSuccessor(Handle successor)
8 {
9
this
.Successor = successor;
10 }
11
public
abstract
void
HandleRequest(RequestStatereqState,ComponentModel comModel);
12
13 }
|
既然有了抽象,那就得有具体的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
1
/// <summary>
2
/// 具体处理者
3
/// </summary>
4
public
class
ConcreteHandlerA : Handle
5 {
6
public
override
void
HandleRequest(RequestState reqState, ComponentModel comModel)
7 {
8
switch
(reqState)
9 {
10
case
RequestState.Check:
11
//执行处理
12
13
break
;
14
case
RequestState.SetDefValue:
15
//执行处理
16
break
;
17
default
:
18
this
.Successor.HandleRequest(reqState, comModel);
19
break
;
20
21 }
22 }
23 }
24
/// <summary>
25
/// 具体处理者
26
/// </summary>
27
public
class
ConcreteHandlerB : Handle
28 {
29
public
override
void
HandleRequest(RequestState reqState, ComponentModel comModel)
30 {
31
switch
(reqState)
32 {
33
case
RequestState.Check:
34
//执行处理
35
break
;
36
case
RequestState.SetDefValue:
37
//执行处理
38
break
;
39
default
:
40
this
.Successor.HandleRequest(reqState, comModel);
41
break
;
42
43 }
44 }
45 }
|
这里的类型应该只定义一个的是为了让大家看的更明白。
在这里看抽象处理者Handle类型,它里面有个protected级别的变量Successor,Successor呢就代表着链表中每一环的指针,指向谁呢?当然是指向下一个处理者。
现在来看一下调用的代码:
1
2
3
4
5
|
1 ComponentModel comModel =
new
ComponentModel();
2 Handle handlerA =
new
ConcreteHandlerA();
3 Handle handlerB =
new
ConcreteHandlerB();
4 handlerA.SetSuccessor(handlerB);
5 handlerA.HandleRequest(RequestState.Check, comModel);
|
看上去已经不错了,耦合度还是很大的,对于handlerA的调用,还是再调用方直接调用的,这时需要一个中间层,
看一下中间层的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
1
/// <summary>
2
/// ChainOfResponsibility模式帮助类
3
/// </summary>
4
public
class
CORUnit
5 {
6
private
Handle _Handle;
7
8
private
ComponentModel _ComModel;
9
10
public
CORUnit(ComponentModel commodel)
11 :
this
(
null
, commodel)
12 {
13 _ComModel = commodel;
14 }
15
public
CORUnit(Handle Handle, ComponentModel commodel)
16 {
17 _Handle = Handle;
18 _ComModel = commodel;
19 }
20
public
void
RegisterHandle(Handle handle)
21 {
22
if
(_Handle !=
null
)
23 {
24 _Handle.SetSuccessor(handle);
//指向 处理链中的下一个 处理模块
25 }
26
else
27 {
28 _Handle = handle;
29 }
30 }
31
public
void
HandleRequest(RequestState reqState)
32 {
33 _Handle.HandleRequest(reqState, _ComModel);
34 }
35 }
|
通过加了一层,再来看一下调用方的代码:
1
2
3
4
5
6
7
|
1 ComponentModel comModel =
new
ComponentModel();
2 CORUnit corunit =
new
CORUnit(comModel);
3 corunit.RegisterHandle(
new
ConcreteHandlerA());
4 corunit.RegisterHandle(
new
ConcreteHandlerB());
5 corunit.HandleRequest(RequestState.Check);
6
//执行处理
7
//comModel的一些处理
|
是不是感觉调用方,跟实际的处理方之间的关系变得很弱了,这样目的也就达到了。
本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1409124,如需转载请自行联系原作者