温故知新(7)——职责链模式

概述

初次听到职责链这个名词,你或许会有一种高深莫测的感觉,我当时就是这样。但如果深入的看下去,发现职责链还真是顾名思义,就是一系列具有相同职责的对象构成一个对象链,由这个对象链去处理一个请求。发出请求的客户端只需知道这个链可以处理这个请求,无需知道这个链的构成和排列。照例给出GOF的意图描述:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

职责链模式有两个要点:

1、存在多个请求的接收者;

2、多个接收者依次处理请求,此处包含了顺序的要求;

3、具体由哪个或哪些接收者处理这个请求可以在运行时决定;

在我理解GOF的意图描述,暗含了接收者要嘛处理请求,要嘛转交请求,也就是所谓的纯职责链。但我认为实际环境中应用更多的应该是非纯职责链,也就是每个接收者对象完成自己的处理操作,然后转交给下一个接收者。就像switch语句中的defult一样,实现时我们也应该提供一个defult接收者,以防止没有接收者处理请求而出错。关于纯职责链与非纯职责链的描述可以参看(http://blog.csdn.net/lovelion/article/details/7420902)。

职责链模式对发送请求的客户与接收请求的接收者进行的了解偶,同时为多个接收者的组织提供较大的灵活性。但是当职责链较长时应该考虑效率问题,实现时也应注意避免链闭合造成无限循环。

结构

职责链模式的类图:

职责链

模式的参与者:

1、定义接受者共同职责的接口——IHandler;

2、接受者的具体实现——HandlerA,HandlerB;

3、客户端程序——Client;

注意IHandler上的自引用,IHandler通常会包含职责链下一环的引用。如果自引用的重数为1时,上图表示的就是经典的职责链;当重数为0…*时“职责链”就演化为“职责树”。关于职责树变体,读者可自行思考。

示例

本示例取自一个基金销售系统。为了吸引用户购买,系统通常需要为基金给出一些推荐标签,如果基金曾经获奖那么给出“获奖基金”的标签,如果业绩出色那么给出“业绩优秀”的标签;如果基金的规模比较大那么给出“规模大”的标签;如果某基金确实没有什么亮点,那么给一个默认的“在售”标签。这些标签的重要性依次降低。

考虑到,给出每种的标签的处理程序职责相同(给予或不给予标签)算法不不同,而且标签有顺序要求,未来这些处理程序可能有增减,因此使用职责链模式比较合适。

1、标签处理接口ILabelProcessor。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.ChainOfResponsibility
 4:  {
 5:      /// <summary>
 6:      /// 职责接口,所有处理者须实现
 7:      /// </summary>
 8:      public interface ILabelProcessor
 9:      {
10:          ILabelProcessor Successor { get; set; }
11:          void TakeLabel(Fund fund);
12:      }
13:  }
14:   

2、标签处理的几个具体实现。

首先是一个抽象类AbstractLabelProcessor,用来处理公用的Successor。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.ChainOfResponsibility
 4:  {
 5:      /// <summary>
 6:      /// 处理者抽象类
 7:      /// </summary>
 8:      public abstract class AbstractLabelProcessor : ILabelProcessor
 9:      {
10:          public AbstractLabelProcessor(ILabelProcessor successor)
11:          {
12:              this.successor = successor;
13:          }
14:   
15:          protected ILabelProcessor successor;
16:   
17:          /// <summary>
18:          /// 后续处理者
19:          /// </summary>
20:          public ILabelProcessor Successor
21:          {
22:              get
23:              {
24:                  return this.successor;
25:              }
26:              set
27:              {
28:                  this.successor = value;
29:              }
30:          }
31:   
32:          public abstract void TakeLabel(Fund fund);
33:      }
34:  }
35:   

“获奖情况”处理者PrizeLabelProcessor。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.ChainOfResponsibility
 4:  {
 5:      /// <summary>
 6:      /// “获奖情况”处理者
 7:      /// </summary>
 8:      public class PrizeLabelProcessor : AbstractLabelProcessor
 9:      {
10:          public PrizeLabelProcessor(ILabelProcessor successor)
11:              : base(successor)
12:          { }
13:   
14:          public override void TakeLabel(Fund fund)
15:          {
16:              if (fund.Code == "100001" || fund.Code == "100002")
17:              {
18:                  fund.Labels.Add("获奖基金");
19:              }
20:              if (this.successor != null)
21:              {
22:                  this.successor.TakeLabel(fund);
23:              }
24:          }
25:      }
26:  }
27:   

“业绩”处理者PerformanceLabelProcessor。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.ChainOfResponsibility
 4:  {
 5:      /// <summary>
 6:      /// “业绩”处理者
 7:      /// </summary>
 8:      public class PerformanceLabelProcessor : AbstractLabelProcessor
 9:      {
10:          public PerformanceLabelProcessor(ILabelProcessor successor)
11:              : base(successor)
12:          { }
13:   
14:          public override void TakeLabel(Fund fund)
15:          {
16:              if (fund.Code == "100002" || fund.Code == "100003")
17:              {
18:                  fund.Labels.Add("业绩优秀");
19:              }
20:              if (this.successor != null)
21:              {
22:                  this.successor.TakeLabel(fund);
23:              }
24:          }
25:      }
26:  }
27:   

“规模”处理者SizeLabelProcessor。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.ChainOfResponsibility
 4:  {
 5:      /// <summary>
 6:      /// “规模”处理者
 7:      /// </summary>
 8:      public class SizeLabelProcessor : AbstractLabelProcessor
 9:      {
10:          public SizeLabelProcessor(ILabelProcessor successor)
11:              : base(successor)
12:          { }
13:   
14:          public override void TakeLabel(Fund fund)
15:          {
16:              if (fund.Code == "100001" || fund.Code == "100003")
17:              {
18:                  fund.Labels.Add("规模大");
19:              }
20:              if (this.successor != null)
21:              {
22:                  this.successor.TakeLabel(fund);
23:              }
24:          }
25:      }
26:  }
27:   

“默认”处理者DefaultLabelProcessor。默认处理者总是处于职责链的末端,所以它没有后继处理者。当没有任何标签时,给出默认标签“在售”。

 1:  using System;
 2:   
 3:  namespace DesignPatterns.ChainOfResponsibility
 4:  {
 5:      /// <summary>
 6:      /// “默认”处理者
 7:      /// </summary>
 8:      public class DefaultLabelProcessor : AbstractLabelProcessor
 9:      {
10:          public DefaultLabelProcessor()
11:              : base(null)
12:          { }
13:   
14:          public override void TakeLabel(Fund fund)
15:          {
16:              if (fund.Labels.Count == 0)
17:              {
18:                  fund.Labels.Add("在售");
19:              }
20:          }
21:      }
22:  }
23:   

3、表示基金的实体类Fund。这里仅保留了很少的内容,实际中此类还包含很多其它信息。

 1:  using System;
 2:  using System.Collections.Generic;
 3:   
 4:  namespace DesignPatterns.ChainOfResponsibility
 5:  {
 6:      /// <summary>
 7:      /// 表示基金的实体类
 8:      /// </summary>
 9:      public class Fund
10:      {
11:          public Fund(string code)
12:          {
13:              this.Code = code;
14:              this.Labels = new List<string>();
15:          }
16:   
17:          /// <summary>
18:          /// 代码
19:          /// </summary>
20:          public string Code { get; set; }
21:   
22:          /// <summary>
23:          /// 标签
24:          /// </summary>
25:          public List<string> Labels { get; set; }
26:      }
27:  }
28:   

4、客户端代码。

 1:  using System;
 2:  using System.Collections.Generic;
 3:   
 4:  namespace DesignPatterns.ChainOfResponsibility
 5:  {
 6:      class Program
 7:      {
 8:          static void Main(string[] args)
 9:          {
10:              //职责链构造
11:              ILabelProcessor defaultLabelProcessor = new DefaultLabelProcessor(); //默认处理者总是处于链的末端。
12:              ILabelProcessor sizeLabelProcessor = new SizeLabelProcessor(defaultLabelProcessor);
13:              ILabelProcessor performanceLabelProcessor = new PerformanceLabelProcessor(sizeLabelProcessor);
14:              ILabelProcessor prizeLabelProcessor = new PrizeLabelProcessor(performanceLabelProcessor);
15:   
16:              //客户端无需了解处理对象的具体情况
17:              ILabelProcessor processor = prizeLabelProcessor;
18:   
19:              string[] codes = { "100001", "100002", "100003", "100004" };
20:              foreach (var code in codes)
21:              {
22:                  Fund fund = new Fund(code);
23:                  processor.TakeLabel(fund);
24:                  Display(fund);
25:              }
26:   
27:              Console.WriteLine("按任意键结束...");
28:              Console.ReadKey();
29:          }
30:   
31:          //展示
32:          private static void Display(Fund fund)
33:          {
34:              Console.Write(fund.Code + ":");
35:              foreach (var label in fund.Labels)
36:              {
37:                  Console.Write(label + " ");
38:              }
39:              Console.WriteLine();
40:              Console.WriteLine("=========================");
41:          }
42:      }
43:  }
44:   

5、运行,查看结果。

image

posted @ 2012-09-11 15:56  宽厚  阅读(1419)  评论(9编辑  收藏  举报