2012-08-31 37 views
5

Tôi đã tạo mẫu kiểu người xây dựng thông thạo để giúp tải dữ liệu về các thử nghiệm của mình. Thứ tự của một số phương pháp là quan trọng và đã tự hỏi những gì các phương pháp ưa thích để quản lý trình tự chính xác là.Cách ưa thích để quản lý đơn đặt hàng trong mẫu trình xây dựng là gì?

Tôi có sau đây vào lúc này:

using NUnit.Framework; 

[TestFixture] 
public class DataBuilderTests 
{ 
    [Test] 
    public void Can_NAME() 
    { 
     new DataLoader() 
      .Start() // must be called first 
      .Setup() // then called next 
      .LoadEmployees() // optional order not NB 
      .LoadProducts() // optional order not NB 
      .StartCleanup() // begin cleanup 
      .CleanupEmployees() // optional order not NB 
      .CleanupProducts() // optional order not NB 
      .End(); 
    } 
} 

public class DataLoader 
{ 
    public DataBuilderSetup Start() 
    { 
     return new DataBuilderSetup(this);  
    } 
} 

public class DataBuilderSetup 
{ 
    private readonly DataLoader _dataLoader; 

    public DataBuilderSetup(DataLoader dataLoader) 
    { 
     _dataLoader = dataLoader; 
    } 

    public DataBuilderOptions Setup() 
    { 
     // do setup 
     return new DataBuilderOptions(_dataLoader); 
    } 
} 

public class DataBuilderOptions 
{ 
    private readonly DataLoader _dataLoader; 

    public DataBuilderOptions(DataLoader dataLoader) 
    { 
     _dataLoader = dataLoader; 
    } 

    public DataBuilderOptions LoadEmployees() 
    { 
     // load 
     return this; 
    } 

    public DataBuilderOptions LoadProducts() 
    { 
     // load 
     return this; 
    } 

    public DataBuilderCleanupOptions StartCleanup() 
    { 
     return new DataBuilderCleanupOptions(_dataLoader); 
    } 
} 

public class DataBuilderCleanupOptions 
{ 
    private readonly DataLoader _dataLoader; 

    public DataBuilderCleanupOptions(DataLoader dataLoader) 
    { 
     _dataLoader = dataLoader; 
    } 

    public DataBuilderCleanupOptions CleanupEmployees() 
    { 
     // cleanup 
     return this; 
    } 

    public DataBuilderCleanupOptions CleanupProducts() 
    { 
     // cleanup 
     return this; 
    } 

    public DataLoader End() 
    { 
     return _dataLoader; 
    } 
} 
+0

Có vấn đề gì với giải pháp hiện tại của bạn? –

+0

Không có gì, chỉ là một cái gì đó tôi đã đưa ra sáng nay và đã tò mò như thế nào những người khác xử lý các kịch bản – Chev

+0

Có 'CleanupEmployees' phải được gọi là nếu' LoadEmployees' được gọi là? –

Trả lời

0

Cách ưa thích là để tránh nó bằng mọi giá. Thiết kế công cụ xây dựng của bạn để rõ ràng những gì cần phải làm.

ObjectBuilder 
.Init() 
.Optional1() 
.Optional3() 
.Optional2() 
.ToObject() 

Nếu điều gì đó cần xảy ra trước thì hãy làm điều này trong phương thức khởi tạo hoặc phương thức nhà máy. Sau đó, luôn luôn có một phương pháp hoàn thành quá trình xây dựng, dọn dẹp và tất cả.

+0

Tôi làm điều này vào lúc này, nhưng hãy tưởng tượng một tình huống mà sự lựa chọn chỉ có thể tồn tại nếu lựa chọn trước đó được sử dụng. Kịch bản điển hình là một mệnh đề OrderBy phổ biến có tiến trình tùy chọn ASC hoặc DESC. Các tùy chọn này sẽ chỉ tồn tại nếu OrderBy được chọn. – Chev

+0

@Chev - Đó thực sự là một kịch bản rất khác. Những gì bạn mô tả thực sự là xây dựng chuỗi. Trong trường hợp đó, bạn sẽ không thể thêm một vị trí mới nơi mà bạn đang xử lý một trình xây dựng mới. Con đường xây dựng sẽ vẫn không rõ ràng. – ChaosPandion

1

Bạn có thể thêm thành viên hàng đợi riêng vào trình tạo, ví dụ: Queue<string> và thêm tên của thao tác trên mỗi bước của trình tạo.

.Build() hoặc trong trường hợp của bạn .End() sẽ kiểm tra hàng đợi chứa tên hoạt động phù hợp theo đúng thứ tự. Nếu không, bạn có thể ném InvalidOperationException

Ngoài ra, bạn có thể sử dụng cây làm cấu trúc dữ liệu. Một cây sẽ cho phép bạn phân tích các tùy chọn không có sẵn cho các bước xây dựng trước đó.

Nhưng tốt hơn hãy xem xét các câu trả lời khác vì cách tiếp cận của tôi thực sự là một hack và nó sẽ tạo ra vấn đề bảo trì.

2

Một phần của thế mạnh của BuilderPattern là nó có thể bảo vệ người tiêu dùng khỏi việc đặt hàng 'ma thuật' được áp đặt của các cuộc gọi phương thức.

Tôi muốn giới thiệu thay đổi thiết kế của bạn để một trong hai:

  • Tất cả các đối số cần thiết được cung cấp lên phía trước để bảo vệ người tiêu dùng khỏi các áp đặt cuộc gọi đến StartSetup.
  • Sửa đổi trách nhiệm của các thực thể của bạn để chúng có thể được xây dựng tùy ý.

Rõ ràng đây là tùy chọn cá nhân của tôi. Nếu loại này tạo thành một phần của thư viện sẽ được các bên thứ ba tiêu thụ thì tôi khuyên bạn nên loại bỏ nhu cầu đặt hàng phương pháp ma thuật. Nếu điều này chỉ có thể được sử dụng trong nhà thì bạn có thể cân nhắc các chi phí liên quan đến việc thay đổi mã của bạn và không làm như vậy.

+0

Thật thú vị, những gì bắt đầu suy nghĩ của tôi là libs bên thứ 3 như FluentNHibernate, FluentValidation và NHibernate chính nó mà dường như làm điều này. – Chev

+0

Đồng ý, nó đánh bại một trong những mục đích chính của một người xây dựng phải gọi các phương thức theo một thứ tự nhất định chỉ để cấu hình nó. Người xây dựng nên lưu trữ các bộ phận và sau đó sắp xếp nó ra trong cuộc gọi Xây dựng cuối cùng. – tcarvin

0

Trong Java (C# và thừa kế nhiều của nó không nên làm cho nó bất kỳ khác nhau), bạn có thể làm nó theo cách đó:

khai báo bộ giao diện, có chứa chỉ có một phương pháp:

Interface DoFirstThing { // could be renamed to "BuilderOnStart" or "BuilderStartingState" 
    DoSecondThing doFirst(); 
} 

Interface DoSecondThing { 
    DoLastThing doSecond(); 
} 

Interface DoLastThing { 
    BuilderReady doLast(); 
} 

Interface BuilderReady { 
    Result build(); 
} 

class BuilderWithForcedSequence implements DoFirstThing, DoSecondThing, DoLastThing, BuilderReady { 

    // implement all 

} 

và cuối cùng, bạn sẽ cần một số phương pháp nhà máy hoặc nhà máy để đặt trạng thái ban đầu cho trình tạo đó:

public DoFirstThing createNewBuilderWithForcedSequence(requiredParameters){ 
    return new BuilderWithForcedSequence(requiredParameters); 
} 

Điều này sẽ tạo ra Trình xây dựng, với lệnh bắt buộc xây dựng meth ods (chúng nên được đổi tên thành doThat thành cái gì đó có ý nghĩa), chỉ có thể gọi doFirst(), sau đó doSecond() ... và cứ như vậy, cho đến khi trạng thái cuối cùng, khi obiect sẽ được xây dựng, sử dụng phương thức build().

Result result = builder.doFirst().doSecond().doLast().build(); 


EDIT:
Rất tiếc, đó là khá chính xác cách tiếp cận của bạn :)

0

giải pháp hiện tại của bạn là cách tiếp cận mà tôi sẽ làm để cung cấp một cú pháp thông thạo, mặc dù tôi sẽ không nhất thiết phải nói nó chính xác theo mô hình của người xây dựng. Về cơ bản, những gì bạn đang làm là xây dựng chuỗi cùng với các hạn chế được cung cấp bởi một máy nhà nước. Tôi thấy rất ít sự khác biệt về những gì bạn đang làm so với bất kỳ cấu hình thông thạo nào được chấp nhận phổ biến khác, chẳng hạn như xác nhận thông thạo ngủ đông hoặc thông thạo.

Các vấn đề liên quan