浅谈.net 中的职责链模式的使用

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

职责链模式的结果如下图

.

 

 

Handler:定义一个处理请求的接口并实现后继链.

ConcreteHandler:处理负责的请求并可访问后继者.如果可处理该请求,则处理之,否则将该请求转发给后继者.

Client:向链上的具体处理者对象提交请求.

 

在这里先用一个简单的例子计算所得税来说明一下职责链模式在应用中的作用

先简要的说一下计算所得税的方法:

以成都为例:

计算金额----------------------应纳税额---------个税率 
1
2000/月以内免税;
2
2000/月以上至2500/----不超过500----5%
3
2500/月以上至4000/----500元至2000----10% 
4
4000/月以上至7000/----2000元至5000----15% 
5
7000/月以上至22000/----5000元至20000----20% 
6
22000/月以上至42000/----20000元至40000----25%
7
42000/月以上至62000/----40000元至60000----30%
8
62000/月以上至82000/----60000元至80000----35%
9
82000/月以上至102000/----80000元至100000----40%
10
102000/月以上----100000元以上----45%

 

(工资-2000)*相应工资范围的个税率

 

当你看到这样的一个计算方式之后你心里是不是已经有了自己的想法了?写一系列的if语句来一条条的判断.但这样的写法虽然可以实现目前的需求,可如果当税率发生了变化你又得拿出你的程序一步一步的修改.如果if语句的条数发生变化的话我们还必须在代码中添加必要的if判断.这对于程序的维护来说是相当麻烦的.如果我们使用职责链模式的话就可以相当简单了.

先说说我们的设计思想.

我们可以采用职责链完成所得税的计算,由职责链上的一个对象负责计算某一段的所得税.如果符合计算条件,则计算;否则由下一个对象计算.这里我们把核心的代码写出来

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CompTax
{
    
public class CompTax
    
{
        
private double Taxp;
        
private double Minincome;
        
private static double Disc=2000;
        
private CompTax NextCompTax;
        
public CompTax(double Minincome, double Taxp)
        
{
            
this.Minincome = Minincome;
            
this.Taxp = Taxp;
            NextCompTax 
= null;
        }

        
public double Comp(double income)
        
{

            
if(income >= Minincome && (NextCompTax==null|| income< NextCompTax.Minincome))
            
{
                
return (income - Disc) * Taxp;
            }

            
else
            
{
                
return NextCompTax.Comp(income);
            }

        }


        
public static CompTax GetInstance()
        
{
            CompTax[] cp 
={
                             new CompTax(0,0),
                             new CompTax(2000,0.05),
                             
new CompTax(2500,0.1),
                             
new CompTax(4000,0.15),
                             
new CompTax(7000,0.2),
                             
new CompTax(22000,0.25),
                             
new CompTax(42000,0.3),
                             
new CompTax(62000,0.35),
                             
new CompTax(82000,0.4),
                             
new CompTax(102000,0.45)
                         }
;
            CompTax ct
=null;
            
for (int i = 0; i < cp.Length-1; i++)
            
{
                
if (i == 0)
                    ct 
= cp[i];
                cp[i].NextCompTax 
= cp[i + 1];
            }

            
return ct;
        }

    }

}

 

 

然后在页面上去调用.

 

        private void button1_Click(object sender, EventArgs e)
        {
            textBox2.Text 
= CompTax.GetInstance().Comp(double.Parse(textBox1.Text)).ToString();
        }

 

 

这样我们在GetInstance静态方法中把处理各种的可能连接了起来.如果第一个对象不能满足就用下一个对象来处理.一直直到能到处理为止.

在这里我们可以把cp这个数组从配置文件中读取,这样就实现了动态配置.

 

说到这个我们还有很多地方可以用到这样的设计模式.比如我们会员积分功能的时候,当积分到了多少就可以做什么事等等也可以用职责链轻松解决了.

 

posted @ 2009-06-25 23:54 杲頔 阅读(2073) 评论(15) 编辑 收藏

 回复 引用 查看   
#1楼 2009-06-26 07:59 stalling240(老S)      
代码很糟糕,没有一行注释
 回复 引用 查看   
#2楼 2009-06-26 08:15 温景良(Jason)      
不知道写啥
 回复 引用 查看   
#3楼[楼主] 2009-06-26 08:40 杲頔      
@一舟
谢谢纠正错误。 忘了2000以下的处理了。

@stalling240(老S)
代码比较简单,基本上用不着写注释,在前面已经把代码的思路提了出来。 如果你只看代码的话可能会有这样的感觉。

 回复 引用 查看   
#4楼 2009-06-26 08:47 Steven Chen      
恩 好像是责任链的每一个node处理的内容不是相同的,这个,策略模式可能好一些

仅个人见解

 回复 引用   
#5楼 2009-06-26 08:57 Null9527[未注册用户]
@stalling240(老S)

需要注释么?

 回复 引用 查看   
#6楼[楼主] 2009-06-26 09:16 杲頔      
@Steven Chen

策略模式思想是一个问题有多个解决方案,特别是在需要不同算法的时候。
比如在做一个加密解密算法的时候,可以使用不同的策略。

而责任链模式重点在让多个对象处理同一个问题,并判断用哪一个对象来处理问题。。 有点像(*J)你不行,他又上。哈哈

 回复 引用 查看   
#7楼 2009-06-26 09:48 疯流成性      
简单明了。很文章
 回复 引用 查看   
#8楼 2009-06-26 10:44 qingniao1981      
没有考虑临界点,应该是income >= Minincome
 回复 引用 查看   
#9楼[楼主] 2009-06-26 10:47 杲頔      
@qingniao1981
谢谢纠正。已修改

 回复 引用 查看   
#10楼 2009-06-26 12:33 麦舒      
用swith语句不是更清晰吗?
 回复 引用 查看   
#11楼[楼主] 2009-06-26 14:00 杲頔      
@麦舒
swith的耦合度太高了。 也不利于动态扩展。

 回复 引用 查看   
#12楼 2009-06-26 14:10 Silent Void      
这个用策略吧,根据金额不同,选择不同的策略。。。

关于职责链,我觉得园子里怪怪的这两篇讲得比较透彻,你可以看看:
模式使用详解——手牵手就是职责链吗
http://www.cnblogs.com/guaiguai/archive/2008/02/18/1071753.html
补充说明: 表驱动, 链表与职责链
http://www.cnblogs.com/guaiguai/archive/2008/02/19/1072942.html

 回复 引用   
#13楼 2009-06-26 14:10 Gray Zhang
关键是要确认此处有修改的可能,并且修改的代价大于使用模式的代价,不然就是滥用模式了
 回复 引用 查看   
#14楼[楼主] 2009-06-26 15:10 杲頔      
@Silent Void

我觉得和策略还是有区别的,在我理解中策略中的任何一种都能解决当前问题。而职责链中只有对应的那一个对象才能处理。
而在这个个税的计算过程中正好符合了这样的条件。

谢谢你推荐的怪怪的两篇文章,让我又多懂了些。

@Gray Zhang
老兄的话很有道理,这里只是用这个例子来说明这种模式,算是武术中的一个招式,在实战中还得看施法者当时的情况而定。

 回复 引用 查看   
#15楼 2009-09-17 13:34 星~无敌      
不对哦,这个算法算出来之后是不对的,没有2000元/月以上至2500元/月 类似段的概念
代码路上