1

复杂对象通常由 Builder 模式创建,其中 Builder 是专用于通过多种方法创建单个对象的对象。EG(伪代码):

class PersonBuilder
    PersonBuilder Named(string name)
        this.name = name
        return this

    PersonBuilder Aged(int age)
        this.age = age
        return this

    Person GetPerson()
        return new Person(this.name, this.age)

这种具有流畅接口的有状态结构在构建器模式中很常见:

myPerson = builder.Named("John").Aged(20).GetPerson();

因此,创建一个可以从中创建构建器的方法是否明智?PersonBuilderFactory或者你应该只依赖 aPersonBuilder并假设你的类将被注入一个新对象?后一种方法意味着当您创建您的时,Person您可能应该重置构建器。这里的最佳实践是什么,为什么?

4

5 回答 5

1

在 C# 中,我喜欢以下模式(需要 lambda 函数):

var person = PersonBuilder.Create(p => p.Named("John").Aged(20));

它在哪里实现是这样的:

class PersonBuilder
{
    private PersonBuilder() { /* ... */ }

    public static Person Create(Action<PersonBuilder> configure)
    {
        var builder = new PersonBuilder();
        configure(builder);
        return builder.Build();
    }

    // ...
}
于 2013-06-14T10:06:19.887 回答
1

在原始的Builder 模式中,有一个 Director。
据我了解,导演将工作与建设者封装在一起。如果您需要以某种方式重置构建器(例如,在构建器中为 TcpClient 调用 dispose),请在 director 中执行此操作。

如何以及在哪里实例化一个具体的构建器?
例如,如果您有 3 种文档格式(TXT、PDF、Excel)并且用户可以从中选择,则在这种情况下您将需要工厂

class BuilderFactory
{
  public IBuilder Create(DocumentType type)
  {
    if(type == DocumentType.TXT)
      return new TxtBuilder();

    if(type == DocumentType.Pdf)
      return new PdfBuilder();

    //...
  }
}

如果在应用程序执行期间构建器相同,您可以将具体构建器放入配置中(尤其是如果您使用 DI)。
如果您在设计时知道具体的构建器,则可以使用 new 运算符。

于 2013-06-14T11:07:17.277 回答
0

这在很大程度上取决于您的构建器类...XXXBuilderFactory当我必须在创建中应用一些逻辑时,我更喜欢创建一个Builder,否则,我认为,只需构建器就足够了,这样代码仍然更简单。

于 2013-06-14T10:09:46.137 回答
0

(由于我的问题的评论者没有选择回答我将提供一个我认为可以接受的答案)

使您的 Builder 不可变是解决此问题的方法。您可以利用一个实例可以访问另一个实例的私有成员这一事实。因此,原始示例变为:

class PersonBuilder
    PersonBuilder(PersonBuilder copy) // copy constructor
        this.name = copy.name
        this.age = copy.age

    PersonBuilder Named(string name)
        newBuilder = new PersonBuilder(this)
        newBuilder.name = name
        return newBuilder

    PersonBuilder Aged(int age)
        newBuilder = new PersonBuilder(this)
        newBuilder.age = age
        return newBuilder

    Person GetPerson()
        return new Person(this.name, this.age)

这样,仍然可以像这样使用构建器:

myPerson = builder.Named("John").Aged(20).GetPerson();

但是,原始的builder对象将保持不变,并且可以重复使用。

感谢本詹姆斯的建议。

于 2013-06-17T15:18:57.183 回答
-1

通常,构建器应该是不可变的,其中不应该有重置的概念。但这仍然取决于您对您需要实现的目标的需求....

于 2013-06-14T10:22:35.637 回答