设计模式杂谈:创建型模式之生成器模式(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  阅读(2114)  评论(16编辑  收藏  举报

导航