了解 C# 中的构建器模式
Understanding Builder Pattern in C#
建造者模式的定义:
Builder 模式将复杂对象的规范与其实际分开
建造。相同的构建过程可以创建不同的表示。
好吧,我有一个这样的构建器模式代码示例
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();
}
}
注:
I have removed the product class from the second sample code.
我的问题是,创建一个 class 来处理所有对象并以有序的方式调用方法使其成为构建器模式?只是想确保我理解构建器模式的概念。
提前致谢
更新 1
我真的不明白为什么第二个示例不是构建器模式。让我创建第二个例子,这对我来说很容易理解,对其他人来说也很容易帮助我理解。下面是代码。
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 Pattern吗?如果不是那么为什么它不是Builder Pattern,请帮助我理解。
恕我直言,这是构建器模式的一个实现。您的实现与您提供的示例之间的唯一根本区别是 "product" 的类型。在您的实现中,您正在制作一个连接字符串(我相信您知道有更简单的方法可以做到这一点!)但是该示例构建了一个 "Product" 类型的对象。
在确定您是否使用构建器模式时,您使用构建器模式构建的内容并不是真正的相关因素。
构建器模式可用于将复杂对象的构造与其表示分开。我不会 class 一个字符串作为一个复杂的对象,值得实现如此复杂的代码,但你仍在使用构建器。
我同意 Filip Cordas 留下的评论,如果您知道如何构建您的示例代码,那么您就可以对其进行调整以满足您的需要。这就是了解设计模式的力量。其他开发人员是否同意您的改编是或不是构建器模式的 "pure" 实现是无关紧要的;希望您已经获得了一些满足您需求的精心设计的代码。
您后面的代码片段不是构建器模式的示例。您 创建 最终对象的步骤是模式的关键部分,通过删除该步骤,您的构建器 class 有效地变成了实际的、构造的(可变的)对象。换句话说,如果 string
是可变的,那么就不存在 StringBuilder
,您只需使用假设的 string.Append
方法来改变最终对象。或者,如果 StringBuilder
return 编辑了构造的 string
以外的任何东西,它就不会被称为 StringBuilder
.
为了证明构建器在实践中的存在,我希望它:
提供一个用于构建不可变对象的接口,然后"freeze"它,即return一个不可变构建的实例(StringBuilder
就是一个很好的例子)。
提供一个稍微干净(例如流畅)的接口来实例化一个对象,相比之下,比如说,有大量的构造函数参数。但是,如果最终对象是可变的,则很难证明这一点,因为无论如何您都可以设置单独的属性。
一些示例使用构建器为构建对象提供额外的抽象层(即允许以相同的方式构建不同的具体类型),然后将抽象构建器传递给 "director"用它来构建对象,但我发现这一步与模式无关。我什至会更进一步说,具有多种方法的抽象构建器感觉像是一种反模式,因为它们将每个具体对象的构建与相同的构建过程联系在一起。为了更好地理解我的观点,请考虑如何在给定的示例 here.
中实现 BoatBuilder
在我看来,这不是构建器模式,但可以简单地更改为。
现在你正在建造的唯一东西就是它自己的建造者。我认为将它变成 "proper" 构建器模式是将您的 GetResult 方法更改为:
public List<string> GetResult()
{
return product;
}
这样您就可以在 IBuilder 中构建一个字符串列表(这是一般规则,通常当您执行复制粘贴时意味着您可能需要重新考虑您的实现)。这些名称可以给你一个线索,你的 get 方法除了打印之外没有得到任何东西。但对我来说,你的实现更糟糕,它违反了 Single responsibility principle。现在,如果您想更改构建过程或想要一种新的显示方式,您 class 可以更改,因为第一个实现只有一个。
建造者模式的定义: Builder 模式将复杂对象的规范与其实际分开 建造。相同的构建过程可以创建不同的表示。
好吧,我有一个这样的构建器模式代码示例
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();
}
}
注:
I have removed the product class from the second sample code.
我的问题是,创建一个 class 来处理所有对象并以有序的方式调用方法使其成为构建器模式?只是想确保我理解构建器模式的概念。 提前致谢
更新 1
我真的不明白为什么第二个示例不是构建器模式。让我创建第二个例子,这对我来说很容易理解,对其他人来说也很容易帮助我理解。下面是代码。
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 Pattern吗?如果不是那么为什么它不是Builder Pattern,请帮助我理解。
恕我直言,这是构建器模式的一个实现。您的实现与您提供的示例之间的唯一根本区别是 "product" 的类型。在您的实现中,您正在制作一个连接字符串(我相信您知道有更简单的方法可以做到这一点!)但是该示例构建了一个 "Product" 类型的对象。
在确定您是否使用构建器模式时,您使用构建器模式构建的内容并不是真正的相关因素。
构建器模式可用于将复杂对象的构造与其表示分开。我不会 class 一个字符串作为一个复杂的对象,值得实现如此复杂的代码,但你仍在使用构建器。
我同意 Filip Cordas 留下的评论,如果您知道如何构建您的示例代码,那么您就可以对其进行调整以满足您的需要。这就是了解设计模式的力量。其他开发人员是否同意您的改编是或不是构建器模式的 "pure" 实现是无关紧要的;希望您已经获得了一些满足您需求的精心设计的代码。
您后面的代码片段不是构建器模式的示例。您 创建 最终对象的步骤是模式的关键部分,通过删除该步骤,您的构建器 class 有效地变成了实际的、构造的(可变的)对象。换句话说,如果 string
是可变的,那么就不存在 StringBuilder
,您只需使用假设的 string.Append
方法来改变最终对象。或者,如果 StringBuilder
return 编辑了构造的 string
以外的任何东西,它就不会被称为 StringBuilder
.
为了证明构建器在实践中的存在,我希望它:
提供一个用于构建不可变对象的接口,然后"freeze"它,即return一个不可变构建的实例(
StringBuilder
就是一个很好的例子)。提供一个稍微干净(例如流畅)的接口来实例化一个对象,相比之下,比如说,有大量的构造函数参数。但是,如果最终对象是可变的,则很难证明这一点,因为无论如何您都可以设置单独的属性。
一些示例使用构建器为构建对象提供额外的抽象层(即允许以相同的方式构建不同的具体类型),然后将抽象构建器传递给 "director"用它来构建对象,但我发现这一步与模式无关。我什至会更进一步说,具有多种方法的抽象构建器感觉像是一种反模式,因为它们将每个具体对象的构建与相同的构建过程联系在一起。为了更好地理解我的观点,请考虑如何在给定的示例 here.
中实现BoatBuilder
在我看来,这不是构建器模式,但可以简单地更改为。 现在你正在建造的唯一东西就是它自己的建造者。我认为将它变成 "proper" 构建器模式是将您的 GetResult 方法更改为:
public List<string> GetResult()
{
return product;
}
这样您就可以在 IBuilder 中构建一个字符串列表(这是一般规则,通常当您执行复制粘贴时意味着您可能需要重新考虑您的实现)。这些名称可以给你一个线索,你的 get 方法除了打印之外没有得到任何东西。但对我来说,你的实现更糟糕,它违反了 Single responsibility principle。现在,如果您想更改构建过程或想要一种新的显示方式,您 class 可以更改,因为第一个实现只有一个。