你的程序装了链条了吗? ---职责链模式
是否你遇到过这样的情况,一个对象可能需要得到很多步复杂过程的处理,而且这些处理步骤的先后顺序和步骤的多少也是不确定的或者是可能经常变动的,常规的做法可能是这样:
如果把各个处理步骤独立出来,自成一体,那效果会是如何呢?我们看代码:
现在我们看看要增加一个处理模块,或改变处理模块的顺序要做些什么呢?大概只是改改配置文件而已吧。
职责链的应用范围其实很广,只要存在一个请求需要一系列对象处理,而且处理对象的执行顺序不定的情况下都可以使用。
好了,任务完成了,休息一下!
如果大家有兴趣,我后面会继续和大家Share常用的设计模式。
1 public class Client
2 {
3 public Client()
4 { }
5
6 public void Treat(SomeObjectType obj)
7 {
8 //first step
9 DoFirstThing(obj);
10 //Second
11 DoSecondThing(obj);
12 //Third
13 DoThirdThing(obj);
14 }
15
16 private void DoFirstThing(SomeObjectType obj)
17 {
18 //
..
19 }
20 private void DoSecondThing(SomeObjectType obj)
21 {
22 //
..
23 }
24 private void DoThirdThing(SomeObjectType obj)
25 {
26 //
..
27 }
28 }
这样的代码会出现什么问题呢?如果我要增加一个处理步骤,怎么办?只有改代码,对吧,如果要将First Step和Third Step换位置怎么办?也只有改代码才能完成,这样的设计是否有违面向对象的一个重要的设计原则:OCP(开放关闭原则),对修改关闭,对扩展开放。2 {
3 public Client()
4 { }
5
6 public void Treat(SomeObjectType obj)
7 {
8 //first step
9 DoFirstThing(obj);
10 //Second
11 DoSecondThing(obj);
12 //Third
13 DoThirdThing(obj);
14 }
15
16 private void DoFirstThing(SomeObjectType obj)
17 {
18 //

19 }
20 private void DoSecondThing(SomeObjectType obj)
21 {
22 //

23 }
24 private void DoThirdThing(SomeObjectType obj)
25 {
26 //

27 }
28 }
如果把各个处理步骤独立出来,自成一体,那效果会是如何呢?我们看代码:
1 public class SomeObjectType
2 {}
3
4
5 public class Client
6 {
7 public Client()
8 { }
9
10 public void Main(string[] Args)
11 {
12 ChildClassA ChildA = new ChildClassA();
13 ChildClassB ChildB = new ChildClassB();
14 ChildA.NextProcessor = ChildB;
15
16 SomeObjectType obj = new SomeObjectType();
17
18 //处理直到职责链的尽头
19 ((IProcess )ChildA).DoProcess(obj);
20 }
21 }
22
23 /// <summary>
24 /// 对象处理接口
25 /// </summary>
26 public interface IProcess
27 {
28 public IProcess Next{set;get;}
29 public void DoProcess(SomeObjectType obj);
30 }
31
32 /// <summary>
33 /// 对象处理基类,使用模板方法模式
34 /// </summary>
35 public class ProcessBase:IProcess
36 {
37 private IProcess m_nextProcessor=null;
38
39 public IProcess NextProcessor
40 {
41 set
42 {
43 m_nextProcessor = value;
44 }
45 get
46 {
47 return m_nextProcessor;
48 }
49 }
50 /// <summary>
51 /// 模板方法
52 /// </summary>
53 /// <param name="obj"></param>
54 public void DoProcess(SomeObjectType obj)
55 {
56 //
do something
57 realDo(obj);
58 //
59 if (m_nextProcessor != null)
60 {
61 m_nextProcessor.DoProcess(obj);
62 }
63 return;
64 }
65
66 /// <summary>
67 /// 该方法将由子类来实现
68 /// </summary>
69 /// <param name="obj"></param>
70 public virtual void realDo(SomeObjectType obj)
71 {
72 //
.
73 }
74 }
75
76 /// <summary>
77 /// 实现类A
78 /// </summary>
79 public class ChildClassA : ProcessBase
80 {
81 public override void realDo(SomeObjectType obj)
82 {
83 base.realDo(obj);
84 //
处理的具体实现
85 //
86 }
87 }
88
89 /// <summary>
90 /// 实现类B
91 /// </summary>
92 public class ChildClassB : ProcessBase
93 {
94 public override void realDo(SomeObjectType obj)
95 {
96 base.realDo(obj);
97 //
处理的具体实现
98 //
99 }
100 }
这样,如果要增加一种处理方式,只需要实现一个继承ProcessBase的就可以了,然后将该处理对象插入到职责链的链条中去,位置当然随你喜好。到了这一步问题还没完全解决,我们增加一个处理类或调换处理顺序还是要去改Client中的代码,我们必须想办法把这段代码改掉,让其依赖配置文件来动态配置。看代码:2 {}
3
4
5 public class Client
6 {
7 public Client()
8 { }
9
10 public void Main(string[] Args)
11 {
12 ChildClassA ChildA = new ChildClassA();
13 ChildClassB ChildB = new ChildClassB();
14 ChildA.NextProcessor = ChildB;
15
16 SomeObjectType obj = new SomeObjectType();
17
18 //处理直到职责链的尽头
19 ((IProcess )ChildA).DoProcess(obj);
20 }
21 }
22
23 /// <summary>
24 /// 对象处理接口
25 /// </summary>
26 public interface IProcess
27 {
28 public IProcess Next{set;get;}
29 public void DoProcess(SomeObjectType obj);
30 }
31
32 /// <summary>
33 /// 对象处理基类,使用模板方法模式
34 /// </summary>
35 public class ProcessBase:IProcess
36 {
37 private IProcess m_nextProcessor=null;
38
39 public IProcess NextProcessor
40 {
41 set
42 {
43 m_nextProcessor = value;
44 }
45 get
46 {
47 return m_nextProcessor;
48 }
49 }
50 /// <summary>
51 /// 模板方法
52 /// </summary>
53 /// <param name="obj"></param>
54 public void DoProcess(SomeObjectType obj)
55 {
56 //

57 realDo(obj);
58 //

59 if (m_nextProcessor != null)
60 {
61 m_nextProcessor.DoProcess(obj);
62 }
63 return;
64 }
65
66 /// <summary>
67 /// 该方法将由子类来实现
68 /// </summary>
69 /// <param name="obj"></param>
70 public virtual void realDo(SomeObjectType obj)
71 {
72 //

73 }
74 }
75
76 /// <summary>
77 /// 实现类A
78 /// </summary>
79 public class ChildClassA : ProcessBase
80 {
81 public override void realDo(SomeObjectType obj)
82 {
83 base.realDo(obj);
84 //

85 //

86 }
87 }
88
89 /// <summary>
90 /// 实现类B
91 /// </summary>
92 public class ChildClassB : ProcessBase
93 {
94 public override void realDo(SomeObjectType obj)
95 {
96 base.realDo(obj);
97 //

98 //

99 }
100 }
1 public class Client
2 {
3 public Client()
4 { }
5
6 public void Main(string[] Args)
7 {
8 //从配置文件获取所有的处理模块的配置信息列表
9 //
10 //通过反射得到处理模块的实例
11 //
12 //对处理模块列表根据配置信息进行组装,将其组合成链条
13 //
14 //调用链条的第一个处理器进行处理
15 //..
16 }
17 }
因为这篇文章是讲职责链模式的,所以这里没有对Client的Main方法进行具体实现,只是写了实现思路,但是从这个思路中大家可以很明确地看到,Client现在只依赖于IProcess接口,不用依赖具体实现,也就是说通过改造,我们对代码进行了解藕,使其更加灵活。2 {
3 public Client()
4 { }
5
6 public void Main(string[] Args)
7 {
8 //从配置文件获取所有的处理模块的配置信息列表
9 //

10 //通过反射得到处理模块的实例
11 //

12 //对处理模块列表根据配置信息进行组装,将其组合成链条
13 //

14 //调用链条的第一个处理器进行处理
15 //..
16 }
17 }
现在我们看看要增加一个处理模块,或改变处理模块的顺序要做些什么呢?大概只是改改配置文件而已吧。
职责链的应用范围其实很广,只要存在一个请求需要一系列对象处理,而且处理对象的执行顺序不定的情况下都可以使用。
好了,任务完成了,休息一下!
如果大家有兴趣,我后面会继续和大家Share常用的设计模式。