了解C#中的Builder模式

时间:2016-10-29 11:17:53

标签: c# design-patterns builder-pattern

构建器模式的定义: Builder模式将复杂对象的规范与其实际分开 施工。相同的构造过程可以创建不同的表示。

我有像这样的Builder Pattern的代码示例

class Director
    {
        // Build a Product from several parts
        public void Construct(IBuilder builder)
        {
            builder.BuildPartA();
            builder.BuildPartB();
            builder.BuildPartB();
        }
    }

    interface IBuilder
    {
        void BuildPartA();
        void BuildPartB();
        Product GetResult();
    }

    class Builder1 : IBuilder
    {
        private Product product = new Product();
        public void BuildPartA()
        {
            product.Add("PartA ");
        }

        public void BuildPartB()
        {
            product.Add("PartB ");
        }

        public Product GetResult()
        {
            return product;
        }
    }

    class Builder2 : IBuilder
    {
        private Product product = new Product();
        public void BuildPartA()
        {
            product.Add("PartX ");
        }

        public void BuildPartB()
        {
            product.Add("PartY ");
        }

        public Product GetResult()
        {
            return product;
        }
    }

    class Product
    {
        List<string> parts = new List<string>();
        public void Add(string part)
        {
            parts.Add(part);
        }

        public void Display()
        {
            Console.WriteLine("\nProduct Parts -------");
            foreach (string part in parts)
                Console.Write(part);
            Console.WriteLine();
        }
    }

    public class Client
    {

        public static void Main()
        {
            // Create one director and two builders
            Director director = new Director();

            IBuilder b1 = new Builder1();
            IBuilder b2 = new Builder2();

            // Construct two products
            director.Construct(b1);
            Product p1 = b1.GetResult();
            p1.Display();

            director.Construct(b2);
            Product p2 = b2.GetResult();
            p2.Display();

            Console.Read();
        }
    }

现在,我在上面的代码中做了一些更改。以下代码是否仍代表构建器模式?

class Director
    {
        public void Construct(IBuilder builder)
        {
            builder.BuildPartA();
            builder.BuildPartB();
            builder.GetResult();
        }
    }

    interface IBuilder
    {
        void BuildPartA();
        void BuildPartB();
        void GetResult();
    }

    class Builder1 : IBuilder
    {
        List<string> product = new List<string>();
        public void BuildPartA()
        {
            product.Add("PartA ");
        }

        public void BuildPartB()
        {
            product.Add("PartB ");
        }

        public void GetResult()
        {
            foreach (var p in product)
            {
                Console.WriteLine("the product created is :" + p);
            }
        }
    }

    class Builder2 : IBuilder
    {
        List<string> product = new List<string>();
        public void BuildPartA()
        {
            product.Add("PartX ");
        }

        public void BuildPartB()
        {
            product.Add("PartY ");
        }

        public void GetResult()
        {
            foreach (var p in product)
            {
                Console.WriteLine("the product created is :" + p);
            }
        }
    }
    public class Client
    {

        public static void Main()
        {

            Director director = new Director();
            IBuilder b1 = new Builder1();
            IBuilder b2 = new Builder2();
            director.Construct(b1);
            director.Construct(b2);

            Console.Read();
        }
    }

注意:

  

我已从第二个示例代码中删除了产品类。

我的问题是,创建一个处理所有对象并以有序方式调用方法的类使它成为Builder模式?只是想确保我理解Builder Pattern的概念。 提前致谢

更新1

我真的无法理解为什么第二个样本不是Builder模式。让我创建第二个例子,这对我来说很容易理解,并且对其他人来说很容易帮助我理解。以下是代码。

 interface IRoutine {
        void WakeUp();
        void GoToSchool();
        void ListenToMusic();
        void Sleep();
    }
    class person1 : IRoutine
    {
        public void GoToSchool()
        {
            Console.WriteLine("going to school");
        }

        public void ListenToMusic()
        {
            Console.WriteLine("litening to music");
        }

        public void Sleep()
        {
            Console.WriteLine("tring to sleep");
        }

        public void WakeUp()
        {
            Console.WriteLine("good morning !!!");
        }
    }
    class person2 : IRoutine
    {
        public void GoToSchool()
        {
            Console.WriteLine("going to school");
        }

        public void ListenToMusic()
        {
            Console.WriteLine("litening to music");
        }

        public void Sleep()
        {
            Console.WriteLine("tring to sleep");
        }

        public void WakeUp()
        {
            Console.WriteLine("good morning !!!");
        }
    }
    class Builder {
        public void Construct(IRoutine routine) {
            routine.WakeUp();
            routine.GoToSchool();
            routine.ListenToMusic();
            routine.Sleep();
        }
    }
    class Client {
        static void Main() {
            Builder builder = new Builder();
            IRoutine r1 = new person1();
            IRoutine r2 = new person2();

            builder.Construct(r1);
            builder.Construct(r2);

            Console.Read();
        }
    }

最近的例子是我提供了Builder模式吗?如果没有那么为什么它不是Builder模式,请帮助我理解。

3 个答案:

答案 0 :(得分:3)

您的后一段代码不是构建器模式的示例。 创建最终对象的步骤是模式的关键部分,通过删除该步骤,构建器类有效地成为实际的,构造的(可变的)对象。换句话说,如果string是可变的,那么就不存在StringBuilder,您只需使用假设的string.Append方法来改变最终对象。或者,如果StringBuilder返回除了已构建的string以外的任何内容,则不会将其称为StringBuilder

为了证明在实践中存在建造者,我希望它能够:

  1. 提供构建不可变对象的接口,然后“冻结”它,即返回不可变构建的实例(StringBuilder就是一个很好的例子)。

  2. 提供一个稍微更清晰(例如流畅)的接口来实例化一个对象,比较一下,比如拥有大量的构造函数参数。但是,如果最终对象是可变的,那么就更难以证明这一点,因为无论如何你都可以设置单独的属性。

  3. 一些示例使用构建器为构建对象提供额外的抽象层(即允许以相同的方式构建不同的具体类型),然后将抽象构建器传递给使用它构建的“director”对象,但我发现这一步与模式无关。我甚至更进一步说,有几种方法的抽象构建器感觉像反模式,因为它们将每个具体对象的构造与同一构建过程联系起来。要更好地理解我的观点,请考虑如何在给定here的示例中实现BoatBuilder

答案 1 :(得分:1)

恕我直言,这是构建器模式的实现。您的实现与您提供的示例之间唯一的根本区别在于“产品”的类型。在您的实现中,您正在创建一个连接字符串(我相信您知道有更简单的方法可以执行此操作!)但该示例构建了一个“Product”类型的对象。

在确定是否使用构建器模式时,使用构建器模式构建的内容实际上并不是一个相关因素。

构建器模式可用于将复杂对象的构造与其表示分开。我不会将字符串分类为一个复杂的对象,值得实现这样复杂的代码,但你仍在使用构建器。

我同意Filip Cordas留下的评论,如果您知道如何构建示例代码,那么您就有能力调整它以满足您的需求。这是了解设计模式的力量。是否另一个开发人员同意您的适应性是否是构建器模式的“纯粹”实现是无关紧要的;你希望得到一些设计良好的代码,以满足你的需求。

答案 2 :(得分:1)

在我看来,这不是一个建设者模式,但可以简单地改变。 现在你唯一要建造的就是它自己的建造者。我认为这将使其成为“适当的”构建器模式,将您的GetResult方法更改为:

public List<string> GetResult()
        {
           return product;
        }

这样您就可以在IBuilder中构建一个字符串列表(这是一般规则,通常在您执行复制粘贴时意味着您可能需要重新考虑实现)。这些名称可以为你提供一个线索,你的get方法除了实际打印之外没有得到任何东西。但对我来说,你实施的剂量更糟糕,它违反了Single responsibility principle。现在,如果您想要更改构建过程或想要一种新的方式来显示它,那么您的类可以更改,因为第一个实现只有一个。