23

Tôi cuối cùng cũng bị ướt chân với Dependency Injection (quá hạn dài); Tôi đã bắt đầu chơi với Unity và gặp phải vấn đề với mô hình chiến lược. Tôi có thể sử dụng container để trả lại cho tôi những triển khai cụ thể của một chiến lược dựa trên một cái tên, nhưng những gì tôi không thấy là làm thế nào tôi có nghĩa vụ phải có được chiến lược đúng trong bối cảnh.
Hãy minh họa trên một ví dụ đơn giản: ngữ cảnh là một chiếc xe, trong đó có một IEngine (chiến lược), với 2 triển khai, FastEngine và SlowEngine. Mã sẽ xem xét theo các dòng sau:Mô hình chiến lược và sự phụ thuộc Tiêm sử dụng Unity

public interface IEngine 
{ 
    double MaxSpeed 
    { 
     get; 
    } 
} 

internal class FastEngine:IEngine 
{ 
    public double MaxSpeed 
    { 
     get 
     { 
      return 100d; 
     } 
    } 
} 

internal class SlowEngine:IEngine 
{ 
    public double MaxSpeed 
    { 
     get 
     { 
      return 10d; 
     } 
    } 
} 

public class Car 
{ 
    private IEngine engine; 
    public double MaximumSpeed 
    { 
     get 
     { 
      return this.engine.MaxSpeed; 
     } 
    } 

    public Car(IEngine engine) 
    { 
     this.engine = engine; 
    } 
} 

Vấn đề của tôi là như sau: Tôi nên làm thế nào để tạo nhanh xe hơi hoặc xe hơi chậm? Tôi có thể sử dụng các container để cung cấp cho tôi với từng thực hiện, và tôi có thể thiết lập một "mặc định" thực hiện để sử dụng:

IUnityContainer container = new UnityContainer(); 
container.RegisterType<IEngine, FastEngine>(); 
container.RegisterType<IEngine, FastEngine>("Fast"); 
container.RegisterType<IEngine, SlowEngine>("Slow"); 
var car = container.Resolve<Car>(); 
Assert.AreEqual(100, car.MaximumSpeed); 

nhưng những gì tôi muốn là để có thể yêu cầu một chiếc xe với một thực hiện cụ thể của chiến lược - giống như

var car = container.Resolve<Car>(??? use "Fast" or "Slow ???); 

Tôi có thể sử dụng vùng chứa để làm điều đó không? Hay tôi nên viết một nhà máy sử dụng container? Bất kỳ hướng dẫn nào cũng sẽ được đánh giá cao - Tôi không chắc tôi đang nghĩ đúng về điều này!

Trả lời

26

Một mẫu phổ biến trong DI là tại thời gian chạy chỉ có một triển khai duy nhất của một sự trừu tượng nhất định. Điều đó chỉ làm cho cuộc sống dễ dàng hơn nhiều, vì bạn không cần phải đối phó với sự mơ hồ như cái bạn mô tả.

Tuy nhiên, đôi khi, bạn cần thay đổi triển khai dựa trên ngữ cảnh, chẳng hạn như ví dụ bạn đưa ra. Nhiều DI Containers cung cấp các cách mà bạn có thể cung cấp thông số đủ điều kiện, nhưng điều đó có nghĩa là bạn sẽ kết thúc chặt chẽ mã của bạn với một vùng chứa DI cụ thể.

Một giải pháp tốt hơn nhiều là giới thiệu một Abstract Factory có thể cung cấp những gì bạn cần. Một cái gì đó như

public interface ICarFactory 
{ 
    Car Create(IEngine engine); 
} 

Nếu bạn cần phải bơm thêm chiến lược, có lẽ là mẫu Builder thiết kế có thể phù hợp thậm chí tốt hơn.

Trong mọi trường hợp, điểm là thay vì đăng ký nhiều Ô tô khác nhau trong vùng chứa, thay vào đó bạn sẽ đăng ký triển khai ICarFactory duy nhất.

Trong mã máy khách của bạn, bạn sẽ sử dụng ICarFactory được tiêm để tạo một cá thể ô tô dựa trên một IEngine cụ thể.

var car = factory.Create(engine); 
+0

Cảm ơn bạn, câu trả lời sâu sắc. Tôi sử dụng mẫu chiến lược, với nhiều chiến lược được hoán đổi vào thời gian chạy, rất nhiều; theo mặc định tôi sẽ làm những gì bạn mô tả (Nhà máy hoặc Builder), nhưng tôi thấy mô hình chiến lược và DI liên quan rất nhiều, và mặc dù điều này có thể giúp đỡ. Từ những gì bạn nói, có vẻ như một container sẽ chỉ hữu ích một chút. – Mathias

+0

Tôi vẫn nghĩ rằng các container cực kỳ hữu ích. Trong những trường hợp này, họ sẽ tiêm nhà máy thay vì chiến lược, nhưng tôi đoán rằng bạn vẫn có thể chọn để triển khai nhà máy với container ... –

+4

Ồ, tôi nghĩ tôi hiểu ý bạn là gì; thay vì trả lại chiếc xe phù hợp, hãy trả lại đúng nhà máy dựa trên động cơ. Trong mọi trường hợp, bình luận của bạn lại: các thùng chứa được sử dụng để cung cấp một triển khai duy nhất cho một trừu tượng là rất hữu ích; nó phù hợp với các ví dụ tôi đã thấy, đó là định hướng cấu hình. Trong khung đó, bạn có thể có một mẫu chiến lược, nhưng một triển khai cụ thể sẽ chỉ có một cấu hình triển khai thực hiện. – Mathias