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

时间:2015-01-26 11:06:20

标签: c# builder

来自Java背景,我必须在C#中实现一些东西。该类是一个域对象,由多个其他域对象组成。我不想拥有一个包含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之间的通话由不同的线程处理,会发生什么?

2 个答案:

答案 0 :(得分:0)

你不需要一个构造函数机智太多的东西....你可能不会调用这些方法的东西,意味着它们中的一些是可选的,我看到的也是我的java,但在这里经过一些回归.NET框架,你可以做得更简单......像这样:

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

如果您没有任何要求,可以删除括号(当您定义可选属性时)。

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

关于你的案例和线程handeling,检查变量的'volatile'语法 - 它确保每个线程调用的字段中的最后一个值

答案 1 :(得分:0)

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

使用您的MyDomainObject类考虑此示例:

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()之后调用任何对象时进行初始化或设置。尝试访问在不同线程中初始化的对象时也是如此。