2012-12-05 39 views
2

讓我告訴你什麼生成器設計模式實現我的每一個博客看到: 生成器設計模式是否違反單一責任原則?

interface IProductBuilder 
{ 
    void BuildPart1(Part1 value); 
    void BuildPart2(Part2 value); 
    void BuildPart3(Part3 value); 
} 

class ConcreteProduct 
{ 
    public readonly Part1 Part1; 
    public readonly Part2 Part2; 
    public readonly Part3 Part3; 

    public ConcreteProduct(Part1 part1, Part2 part2, Part3 part3) 
    { 
     Part1 = part1; 
     Part2 = part2; 
     Part3 = part3; 
    } 
} 

class ConcreteProductBuilder : IProductBuilder 
{ 
    Part1 _part1; 
    Part2 _part2; 
    Part3 _part3; 

    public void BuildPart1(Part1 value) 
    { 
     _part1 = value; 
    } 

    public void BuildPart2(Part2 value) 
    { 
     _part2 = value; 
    } 

    public void BuildPart3(Part3 value) 
    { 
     _part3 = value; 
    } 

    public ConcreteProduct GetResult() 
    { 
     return new ConcreteProduct(part1, part2, part3); 
    } 
} 

到單元測試生成器的常見方法是這樣的:

[TestMethod] 
void TestBuilder() 
{ 
    var target = new ConcreteBuilder(); 

    var part1 = new Part1(); 
    var part2 = new Part2(); 
    var part3 = new Part3(); 

    target.BuildPart1(part1); 
    target.BuildPart2(part2); 
    target.BuildPart3(part3); 

    ConcreteProduct product = target.GetResult(); 

    Assert.IsNotNull(product); 
    Assert.AreEqual(product.Part1, part1); 
    Assert.AreEqual(product.Part2, part2); 
    Assert.AreEqual(product.Part3, part3); 
} 

所以,這是一個非常簡單的例子。

我認爲建造者模式是一個非常好的事情。它使您能夠將所有可變數據放在一個地方,並讓所有其他類不變,這對於可測試性來說是很酷的。

但是如果我不希望暴露產品領域的人(或我,因爲產品是一些圖書館的一部分,只是不能做到這一點)。

我單位應如何測試我的建設者?

它看起來現在這個樣子?

[TestMethod] 
void TestBuilder() 
{ 
    var target = new ConcreteProductBuilder(); 

    var part1 = new Part1(); 
    var part2 = new Part2(); 
    var part3 = new Part3(); 

    target.BuildPart1(part1); 
    target.BuildPart2(part2); 
    target.BuildPart3(part3); 

    ConcreteProduct product = target.GetResult(); 

    TestConcreteProductBehaviorInUseCase1(product); 
    TestConcreteProductBehaviorInUseCase2(product); 
    ... 
    TestConcreteProductBehaviorInUseCaseN(product); 
} 

在這裏,我看到至少有一個簡單的解決方案 - 修改ConcreteProductBuilder.GetResult採取一廠:

public ConcreteProduct GetResult(IConcreteProductFactory factory) 
{ 
    return factory.Create(part1, part2, part3); 
} 

和實施IConcreteProductFactory在2種方式:

public MockConcreteProductFactory 
{ 
    public Part1 Part1; 
    public Part2 Part2; 
    public Part3 Part3; 
    public ConcreteProduct Product; 
    public int Calls; 

    public ConcreteProduct Create(Part1 part1, Part2 part2, Part3 part3) 
    { 
     Calls++; 

     Part1 = part1; 
     Part2 = part2; 
     Part3 = part3; 

     Product = new ConcreteProduct(part1, part2, part3); 
     return Product; 
    } 
} 

public ConcreteProductFactory 
{ 
    public ConcreteProduct Create(Part1 part1, Part2 part2, Part3 part3) 
    { 
     return new ConcreteProduct(part1, part2, part3); 
    } 
} 

在這種案例測試將像以前一樣簡單:

[TestMethod] 
void TestBuilder() 
{ 
    var target = new ConcreteBuilder(); 

    var part1 = new Part1(); 
    var part2 = new Part2(); 
    var part3 = new Part3(); 

    target.BuildPart1(part1); 
    target.BuildPart2(part2); 
    target.BuildPart3(part3); 

    var factory = new MockConcreteProductFactory(); 

    ConcreteProduct product = target.GetResult(factory); 

    Assert.AreEqual(1, factory.Calls); 
    Assert.AreSame(factory.Product, product); 
    Assert.AreEqual(factory.Part1, part1); 
    Assert.AreEqual(factory.Part2, part2); 
    Assert.AreEqual(factory.Part3, part3); 
} 

所以我的問題不是關於如何解決它一個更好的方法,而是關於生成器模式本身。

是否生成器設計模式違反了單一職責原則?

對於我來說,它看起來是建造在一個共同的定義是負責:構造參數(或屬性值在其他實現生成器模式的)

  • 構建對象

    1. 收集與收集性能
  • 回答

    1

    我們正在處理的兩個概念在這裏:

    是建造者模式尊重單一職責原則? 是的。

    你可能會認爲,製造商有兩個職責:根據所收集的性能

    事實上

    • 收集性能
    • 創建產品,只有一個責任,就是創造該產品基於收集的屬性。 您知道,負責收集房產的班級是導演班級(請參閱Wikipedia link)。建設者只有收到屬性在被動的方式。這不是它的責任。在收到屬性後,它會構建該對象。

      單元測試怎麼樣?

      那麼,從技術上講,當你不想在一個模式中公開字段,這是一個原因,它是你的核心設計的一部分。因此,容納單元測試儀不是「設計」的工作。適應「設計」是單元測試人員的工作。

      你可以通過反射來實現(好吧,那就是作弊)或者購買創建一個繼承你想測試的混凝土生成器的模型生成器。這個模型構建器會存儲它組裝的部分,並使它們可以被單元測試人員訪問。

    2

    我不認爲這違反單一職責原則(SRP)。考慮在維基SRP提到的例子:

    馬丁界定責任的理由去改變,並得出結論,一類或模塊應該有一個,且只有一個理由去改變。作爲一個例子,考慮一個編譯和打印報告的模塊。出於兩個原因可以更改這種模塊。首先,報告的內容可能會改變。其次,報告的格式可能會改變。這兩件事情因非常不同的原因而改變。一個實質性的,一個化妝品。

    但是,對於你提到的情況,如果一個改變另一個也必須改變,即如果有一個額外的參數,那麼該對象應該用這個額外的參數構造。所以它主要負責2個子任務。

    相關問題