2016-07-05 18 views
7

Tôi có danh sách các Trình tạo Dữ liệu (đang phát triển). Máy phát điện mà tôi cần được tạo bởi một lớp nhà máy. Tất cả các máy tạo đều thực hiện một Giao diện chung, bao gồm một số thứ khác là một chuỗi tĩnh name.Mẫu Nhà máy, chọn theo Thuộc tính

Điều tôi muốn làm: Gọi phương thức factory.reate với thông số chuỗi cho tên được đề cập ở trên. Phương thức create tìm máy phát với tên này và trả về một cá thể mới của trình tạo đã nói.

Tiền thưởng theo ý kiến ​​của tôi về cách này để làm điều đó: Tôi chỉ phải thêm các lớp máy phát điện mới mà không phải chỉnh sửa nhà máy.

Câu hỏi:

  1. Đây có phải là một cách tốt để xử lý vấn đề này?
  2. Tôi làm cách nào để tìm tất cả máy phát? Phản ánh trên mọi thực hiện của giao diện/mọi thành viên của không gian tên (duy nhất cho các máy phát + giao diện của họ)?
  3. Có đúng không khi gọi cách này để làm việc một nhà máy, hoặc đây có phải là một mô hình khác không?

Cuối cùng tôi sẽ gọi cho nhà máy như thế này (giản thể):

//Caller 
public DataModel GetData2() 
{ 
    var generator = new DataFactory().Create("Gen.2"); 
    return generator.GetData(); 
} 

//Factory 
public class DataFactory 
{ 
    public AbstractDataGenerator Create(string type) 
    { 
     //Here the magic happens to find all implementations of IDataGenerator 
     var allGenerators = GetImplementations(); 
     var generator = allGenerators.FirstOrDefault(f => f.name == type); 
     if (generator != null) 
      return (AbstractDataGenerator)Activator.CreateInstance(generator); 
     else 
      return null; 
    } 
} 

//Interface 
public abstract class AbstractDataGenerator 
{ 
    public static string name; 
    public abstract DataModel GetData(); 
} 

//Data-Generators 
public class DataGen1 : AbstractDataGenerator 
{ 
    public static string name = "Gen.1"; 
    public DataModel GetData() 
    { 
     return new DataModel("1"); 
    } 
} 
public class DataGen2 : AbstractDataGenerator 
{ 
    public static string name = "Gen.2"; 
    public DataModel GetData() 
    { 
     return new DataModel("2"); 
    } 
} 

nên sự kỳ diệu GetImplementations() trong nhà máy được thực hiện thông qua Reflection hoặc bằng cách nào đó khác nhau? Tôi có nên sử dụng một cách tiếp cận hoàn toàn khác không?

Vì câu trả lời tham chiếu đến IoC và DI: Dự án này sử dụng NInject, vì vậy nó sẽ có sẵn. Chuyển từ giao diện sang lớp trừu tượng.

+0

Một vấn đề tôi đã tìm thấy với phương pháp này là để có được sự "Tên" tài sản của các máy phát điện bạn _need một thể hiện của các object_. – stuartd

+0

Đó là lý do tại sao tôi đã tạo thuộc tính tĩnh. Điều này sẽ loại bỏ sự cần thiết cho một trường hợp, nếu tôi không nhầm. – MilConDoin

+0

Giao diện không thể có thành viên tĩnh .. – stuartd

Trả lời

4

Đây có phải là cách hay để xử lý sự cố này không?

Có một nhà máy để có được một thể hiện của lớp logic bạn cần bằng một số khóa - Tôi tin rằng đó là một cách tốt. Đó là một mô hình mà tôi sử dụng rất nhiều. Về cách bạn có chìa khóa của bạn - Tôi muốn không có nó như là một thành viên static (bất kể thực tế là giao diện không thể có các thành viên tĩnh) nhưng chỉ là một property và thêm một lớp cơ sở để IDataGenerator. Lớp cơ sở đó sẽ có một hàm tạo sẽ nhận được name - Bằng cách đó, mỗi DataGenerator mới mà bạn tạo sẽ phải thiết lập nó và bạn sẽ không quên.


Về có name như một string - Cá nhân tôi thích có nó "mạnh mẽ gõ".Ý tôi là nếu tôi vượt qua Gen . 2 thay vì Gen.2 bằng các chuỗi, tôi sẽ chỉ phát hiện vấn đề này trong thời gian chạy. Có thể những cách khác (nếu bạn muốn, bởi vì một chuỗi đơn giản là tốt quá - một vấn đề của hương vị):

  • Thay thế chuỗi với một enum
  • Có một lớp tĩnh với chuỗi readonly tĩnh cho tất cả các giá trị của bạn - sau đó trong mã của bạn sử dụng các giá trị đó. Bạn nhận được lợi ích của intellisense và không nhận được chuỗi sai nhưng tốt hơn enum - bạn chỉ có thể vượt qua dây mà không có trong danh sách "" để bạn có thể thêm những cái mới như add-ons.
  • Có đối tượng RequestGenerator, với mỗi GeneratorIDataGenerator<TGeneratorRequest>. Điều này có thể là một quá mức cần thiết nhưng nếu bạn cũng có thêm thông tin bạn cần cho việc tạo ra một DataGenerator mà khác nhau giữa chúng sau đó xem xét nó.

Tôi làm cách nào để tìm tất cả máy phát? Phản ánh trên mọi thực hiện của giao diện/mọi thành viên của không gian tên (duy nhất cho các máy phát + giao diện của họ)?

Có, phản ánh có thể là cách hay để làm như vậy. Tuy nhiên, tôi khuyên bạn nên đọc thành Dependency InjectionIoC Containers chẳng hạn như Castle Windsor chẳng hạn. Có những điều ra khỏi đó mà đã thực hiện nó cho bạn, vậy tại sao để tái phát minh ra bánh xe :)

DI là một khái niệm thay đổi cuộc sống theo ý kiến ​​của tôi

Là nó đúng để gọi theo cách này làm việc một nhà máy, hoặc là một số mô hình khác nhau?

Yap. Đây là một số Factory

Nếu phép thuật GetImplementations() trong nhà máy được thực hiện qua Phản xạ hoặc bằng cách nào đó khác?

Xem câu trả lời cho câu hỏi 2

+0

Ý tưởng bổ sung của bạn với một lớp tĩnh chứa các chuỗi cố định tĩnh đã sẵn sàng thực hiện :) Tôi đã sử dụng chuỗi ma thuật trong ví dụ của tôi ở trên ngoài sự đơn giản. – MilConDoin

+0

Tốt :). Tôi cũng nói rằng cách chọn "khóa" của bạn cho nhà máy khác nhau về cách mã này được trưng ra. Nếu nó được ẩn đằng sau một mặt tiền và là loại chi tiết thực hiện của riêng bạn thì nó không thực sự quan trọng tùy chọn nào. Tuy nhiên nếu nó được tiếp xúc bằng cách nào đó để sử dụng bên ngoài, tôi muốn các tùy chọn 'enum' hoặc' TRequest' - một giao diện rõ ràng hơn nhiều so với 'string' cho những người khác –

2

Đây là nơi mà việc xây dựng hệ thống phun có thể thực sự tỏa sáng. Nhìn vào công cụ tiêm phụ thuộc và sử dụng một! Nó cũng kiểm tra yêu cầu "Tiền thưởng" của bạn.

Đây là những gì nhà máy của bạn có thể trông giống như với constructor tiêm:

public class DataFactory 
{ 
    private Dictionary<string, IDataGenerator> generators; 

    public DataFactory(IDataGenerator[] generatorReferences) 
    { 
     this.generators = generatorReferences 
      .ToDictionary(k => k.name, v => v); 
    } 
    public IDataGenerator Create(string type) 
    { 
     IDataGenerator generator = null; 
     this.generators.TryGetValue(type, out generator); 
     return generator; 
    } 
} 

phần mềm Hầu hết DI có khả năng tự động quét hội cho triển khai của một loại nhất định (ví dụ IDataGenerator) và đăng ký những người có chính nó, khi nó xây dựng một thể hiện của DataFactory của bạn nó sẽ tự động bao gồm chúng.

+0

Tôi đang sử dụng NInject. Đơn giản chỉ cần có một mảng của giao diện trong constructor là không đủ, vì vậy tôi có thể phải làm một số ràng buộc trước. Bây giờ để đảm bảo rằng, có một số cách đơn giản để làm điều này, mà không cần phải làm phản xạ mở rộng, mà tôi có thể làm trực tiếp mà không có NInject. – MilConDoin

+0

Tôi đã sử dụng Ninject trong nhiều năm, một mảng sẽ hoạt động tốt. Chỉ cần đăng ký tất cả các trường hợp bạn có và nó sẽ được tiêm.Nếu tôi nhớ chính xác những điều sau được hỗ trợ [], IEnumerable , Danh sách . Lưu ý rằng khi được tiêm qua IEnumerable , nó sẽ được tải và đánh giá lại theo từng liệt kê, vì vậy hãy cẩn thận với điều đó. –

+0

Có cách nào dễ dàng và tự động để đăng ký tất cả các trường hợp thực hiện giao diện/xuất phát từ lớp cha? Tôi không tốt với NInject. – MilConDoin

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