我的构建器设计模式是线程安全的吗?

Is my builder design pattern thread-safe?

来自 Java 背景,我必须用 C# 实现一些东西。 class 是由多个其他域对象组成的域对象。我不喜欢有 10 个字段的构造函数,所以我想到了使用构建器设计模式!这是我想出的:

public class MyDomainObject
{
  public DomainObject1 Obj1 { get; private set; }
  public DomainObject2 Obj2 { get; private set; }
  public DomainObject3 Obj3 { get; private set; }
  ...

  public class DomainObjectBuilder
  {       
    private MyDomainObject _domainObj = new MyDomainObject();

    public DomainObjectBuilder(DomainObject1 obj1)
    {
        _domainObj.Obj1 = obj1;
    }

    public DomainObjectBuilder withDomainObject2(DomainObject2 obj2)
    { 
        _domainObj.Obj2 = obj2; 
        return this;    
    }

    .....  

    public MyDomainObject Build()
    {
      // Construct and Return the MyDomainObject
    }
  }
}

现在这个实现线程安全吗?当我通过以下方式实例化我的域对象时:

var myDomainObject = new DomainObjectBuilder(obj1)
                         .withDomainObject2(obj2)
                         .withDomainObject3(obj3).build();

如果 withDomainObject2withDomainObject3 之间的调用由不同的线程处理会怎样?

你不需要一个包含太多东西的构造函数....你可能不会调用其中一些方法,这意味着其中一些是可选的,我也看到了 java,但是在对 .NET 框架进行一些复原之后,您可以更简单地完成它...像这样:

A a = new A(Required properties){
    Name="x",
    Family="Y",
    OpetionalProperty3 = "z",
    .......
};

如果您不需要任何东西,您可以完全删除括号(当您定义可选属性时)。

A a = new A{
    Name="x",
    Family="Y",
    OpetionalProperty3 = "z",
    .......
};

关于您的案例和线程处理,请查看变量的 'volatile' 语法 - 它确保最后一个值在每个线程调用的字段中

我还没有遇到任何在多个线程上拆分生成器的代码。给出您的要求的简单答案很简单(不,它不是线程安全的)。

使用您的 MyDomainObject class:

考虑这个例子
private MyDomainObject _myObj;

    void Main(string[] args)
    {
        DomainObject1 obj1 = new DomainObject1();   
        _myObj = new MyDomainObject(obj1);

        Thread oThread1 = new Thread(ThreadProc1);
        oThread1.Start();

        Thread oThread2 = new Thread(ThreadProc2);
        oThread2.Start();

        MyDomainObject myObjFinal = _myObj.Build();

        DomainObject2 obj2 = myObjFinal.Obj2; //No guarantee that Obj2 is set or initialized
        DomainObject3 obj3 = myObjFinal.Obj3; //No guarantee that Obj3 is set or initialized

    }

    void ThreadProc1()
    {
        DomainObject2 obj2 = new DomainObject2();
        MyDomainObject myObjModified = _myObj.withDomainObject2(obj2);

        DomainObject3 objNew = _myObj.Obj3; //No guarantee that Obj3 is set or initialized

    }

    void ThreadProc2()
    {
        DomainObject3 obj3 = new DomainObject3();
        MyDomainObject myObjModified = _myObj.withDomainObject3(obj3);

        DomainObject2 objNew = _myObj.Obj2; //No guarantee that Obj2 is set or initialized
    }

如您所见,无法保证在主线程中 Build() 之后调用时任何对象都已初始化或设置。这同样适用于尝试访问在不同线程中初始化的对象。