licongjie的博客

专心、专注、专业
随笔 - 26, 文章 - 1, 评论 - 207, 引用 - 1
数据加载中……

设计模式杂谈:创建型模式之生成器模式(Builder Pattern)

      前几讲链接:
      1、设计模式杂谈:开头篇
      2、设计模式杂谈:创建型模式之工厂方法(Factory Method)
      3、设计模式杂谈:创建型模式之单件模式(Singleton)
      4、设计模式杂谈:创建型模式之抽象工厂模式(Abstract Factory) 

      关于设计模式的杂谈,已经断断续续写了四篇了,但反应好象不怎么样,呵呵,大家都对设计模式不陌生了,再加上这几篇又是很简单的东西,所以没有多少价值,不过不管怎么样,既然写了,还是继续了,给自己一个总结的机会。

      好了,不说废话了,开门见山吧。这讲我主要讲生成器模式,这种模式主要是用来解决“复杂对象的创建”,这类所谓的复杂对象,往往有好几个部分组成,也可以说有好多个算法组成。而往往这些子部分和算法是经常变化的,但是组合在一起的总的算法是相对稳定的。这个时候,我们就可以用生成器模式来解决此类问题。生成器模式需要创建一系列的对应的生成器类,内部封装各子部分或子算法的实现以及最终结果的返回,当具体使用时,实例化需要用到的生成器类,再通过一个指导员角色的类来指示这些子算法的执行,最后可以根据这些算法返回最终我们需要的结果。

      还是按照我以前的思维,通过对原来案例的重构来说明生成器模式的运用场合。在那个案例中,员工工资的的计算,需要通过基本工资、奖金和个人所得税来计算得出,不管是美国公司还是中国公司都是如此,在对抽象工厂的讲述中,我们已经把奖金和个人所得税的计算单独出来,做为一个子部分,再通过这二个子部分去最终得出员工工资,我们可以从这里开始进一步重构。从另一个角度去看这个问题,我们就会发现,对于这二个公司来说,最终的计算员工工资的算法是相对稳定的,而实现这个最终算法的其它部分,如奖金计算和个人所得税的计算是需要变化的。所以,这个解决方案,我们还可以通过生成器模式来解决。

      好,接下来,我们来看具体的实际运用,至于奖金和个人所得税的计算方法跟上一讲中抽象工厂模式里的一样,这里就不再帖出来了,有兴趣的朋友可以看一下上一讲内容。所以,接下来我们要做的就是如何来创建生成器类,上面也提到了,该生成器是用来进行子算法计算的以及最终结果的返回,因此,我们需要二个方法来对应奖金和个人所得税的计算,这二个不需要返回值,最后还需要一个方法来计算最终结果并返回,返回值为double型。

      从上面的分析中,我们先来创建该生成器的接口,代码如下:

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5namespace DesignPattern.IBLL
 6{
 7    public interface IBuilder
 8    {
 9        void CalculateBonus(double basicSalary);
10
11        void CalculateTax(double basicSalary);
12
13        double GetSalary(double basicSalary);
14    }

15}

16

      接下来,针对美国公司和中国公司分别实现该接口:
      
      美国公司:
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5namespace DesignPattern.Factory
 6{
 7    public class AmericanBuilder : IBLL.IBuilder
 8    {
 9        private double _bonus;
10        private double _tax;
11        private double _salary;
12
13        public void CalculateBonus(double basicSalary)
14        {
15            IBLL.IBonus bonus = new BLL.AmericanBonus();
16            _bonus = bonus.GetBonus(basicSalary);
17        }

18
19        public void CalculateTax(double basicSalary)
20        {
21            IBLL.ITax tax = new BLL.AmericanTax();
22            _tax = tax.GetTax(basicSalary);
23        }

24
25        public double GetSalary(double basicSalary)
26        {
27            _salary = _bonus + basicSalary - _tax;
28
29            return _salary;
30        }

31
32    }

33}

34

      中国公司:
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5namespace DesignPattern.Factory
 6{
 7    public class ChineseBuilder : IBLL.IBuilder
 8    {
 9        private double _bonus;
10        private double _tax;
11        private double _salary;
12
13        public void CalculateBonus(double basicSalary)
14        {
15            IBLL.IBonus bonus = new BLL.ChineseBonus();
16            _bonus = bonus.GetBonus(basicSalary);
17        }

18
19        public void CalculateTax(double basicSalary)
20        {
21            IBLL.ITax tax = new BLL.ChineseTax();
22            _tax = tax.GetTax(basicSalary);
23        }

24
25        public double GetSalary(double basicSalary)
26        {
27            _salary = _bonus + basicSalary - _tax;
28
29            return _salary;
30        }

31
32    }

33}

34


      (注:或许有人认为这里对于CalculateTax和CalculateBonus的计算,没有必要再去单独出来一个类了,让人感觉这里有点过度设计。)

        最后,我们还需要一个指导员角色的类来指导这些对象的生成:

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4
 5namespace DesignPattern.Common
 6{
 7    public class SalaryManager
 8    {
 9        private double basicSalary;
10
11        public SalaryManager(double basicSalary)
12        {
13            this.basicSalary = basicSalary;
14        }

15
16        public void Construct(IBLL.IBuilder builder)
17        {
18            builder.CalculateBonus(basicSalary);
19
20            builder.CalculateTax(basicSalary);
21        }

22    }

23}

24

      其中的Construct方法,通过传进来的生成器,来指导内部算法的执行。

      最终程序调用如下:

 1 double basicSalary = Convert.ToDouble(txtBasicSalary.Text.Trim());
 2                double salary;
 3
 4                SalaryManager salaryManager = new SalaryManager(basicSalary);
 5
 6                salaryManager.Construct(FactoryUtility.Factory);
 7
 8                salary = FactoryUtility.Factory.GetSalary(basicSalary);
 9
10                lbSalary.Text = salary.ToString();

      呵呵,终于写完了。写文章真是累的,不管是简单还是复杂。这几篇杂谈也主要是想表达在不同的思考方式上,可以有不同的解决方案,况且象我讲的几篇中,不管是工厂方法、抽象工厂还是生成器模式,都有相似的地方,这几篇内容通过重构的方法,对这几种模式进行了比较,从而增加认识的程度。

      由于本人对设计模式的认识也不怎么深刻,写出来的东西自然也不怎么样,这一点还请多多包涵了。

      源代码下载(生成器模式)

posted on 2006-12-14 10:26 李.net 阅读(1489) 评论(17)  编辑 收藏 所属分类: Design & Pattern

评论

#1楼    回复  引用  查看    

不错, 还是比较容易理解的.
2006-12-14 11:01 | Rice[匿名] [未注册用户]

#2楼 [楼主]   回复  引用  查看    

@Rice[匿名]
呵,谢谢关注
2006-12-14 11:02 | 李.net      

#3楼    回复  引用  查看    

为什么非要写代码?
用图不是更好吗?
感觉你写了这么多
放在首页还是不合适的
重复别人做过的事
低级的重复
而且比以前的要逊色许多!
不过对自己的学习一定很有帮助
对大家来说的话
看吕震宇的要比看这个收获更多!
2006-12-14 11:15 | F4 [未注册用户]

#4楼 [楼主]   回复  引用  查看    

@F4
是的,他们几个写的确实比较经典,这个我不否认。对你可能没用,对有些人有点用就可以了,如果你觉得你写的会更好的话,为什么不拿出来共享呢。
用图,我到不觉得用图会更好,设计模式本来就是很抽象的东西,再用图这种抽象的东西来表达,对刚刚接触设计模式的人来说更模糊,难道不是吗?
当然,不否认图加上代码能够更好的理解。
2006-12-14 11:36 | 李.net      

#5楼 [楼主]   回复  引用  查看    

@F4
而且我也不觉得重复,这是我个人的想法,每个人的想法都不一样,理解的程度都不一样,我写的虽然简单,但有时候简单更容易理解。
2006-12-14 11:37 | 李.net      

#6楼    回复  引用  查看    

支持 @李.net 个人的理解是不同的.
不一定要经典的东西才拿出来分享的,只要实用易懂就好!
2006-12-14 12:57 | 缘易姿姿[匿名]      

#7楼 [楼主]   回复  引用  查看    

@缘易姿姿[匿名]
呵呵,谢谢支持。
2006-12-14 13:12 | 李.net      

#8楼    回复  引用  查看    

根据楼主所说的理解
这个发到新手区比较合适
怎么说这是个专业的.net社区,随笔发到首页的文章是有要求的
发的时候楼主看了吗?
2006-12-14 13:31 | F4 [未注册用户]

#9楼 [楼主]   回复  引用  查看    

@F4
这个每个人的想法都不一样,我认为我放在这里没有问题,你认为放在这里有问题,你觉得有这个必要在这里争论吗?
2006-12-14 13:41 | 李.net      

#10楼 [楼主]   回复  引用  查看    

为什么园子里老有一个叫“580K”的来做广告呢。刚刚删除一个。
2006-12-14 15:50 | 李.net      

#11楼    回复  引用  查看    

虽然很简单,但对初学者来说还是很有价值的
望再接再厉!:)

#12楼 [楼主]   回复  引用  查看    

@麒麟.NET[匿名]
:)
2006-12-14 16:15 | 李.net      

#13楼    回复  引用  查看    

从之前几篇来看,宣传的成分越来越浓了,带来的收获越来越小
虽然苦苦写了这么多,但我认为还是应该放在新手区.
发原创也要遵守大家的规则吧,对新手有用就放在新手区.
2006-12-14 18:17 | 极地银狐.NET      

#14楼    回复  引用  查看    

过于基本了,楼主是否应该尝试多在文章里面加入点自己的体会和感悟,Builder模式为什么要这么设计?是需求的变化所驱动的,那么是否可以围绕需求的变化来掩饰一下Builder模式的应对策略,从而更加深刻的阐述设计思想呢~
2007-01-28 19:02 | shenfx      

#15楼    回复  引用  查看    

入门好心法
2007-03-12 12:24 | c#游子 [未注册用户]

#16楼    回复  引用  查看    

我还是觉得你写的比较好理解
至少我看明白了
2008-03-11 16:55 | 状元