2009-06-10 26 views
7

Tôi đã đọc về tiêm phụ thuộc và có một câu hỏi đơn giản. Tôi có thể hiểu làm thế nào thông qua constructor hoặc setter tiêm phụ thuộc yêu cầu được autowired bởi khuôn khổ DI. Điều gì xảy ra khi một đối tượng quyết định nó cần tạo một đối tượng mới do một số quy trình nghiệp vụ? Tôi có cần phải luôn tạo một Nhà máy trong những tình huống này không? Để làm cho nó một câu hỏi ít trừu tượng hơn, đây là một ví dụ.Câu hỏi về New Dependency Injection khi một phương pháp cần tạo đối tượng mới

Giả sử tôi đang viết trò chơi Asteriod. Có một con tàu ở giữa có thể quay xung quanh và bắn các tiểu hành tinh. Giả sử rằng con tàu đã được tạo ra và gây ra những thứ bị tiêm chích. Khi playerShip.shoot() được gọi là chúng ta cần tạo đối tượng bullet. Đối tượng viên đạn cần phải biết cách nó đang đi (direction) và bắt đầu từ đâu (point).

Thông thường, tôi sẽ làm một cái gì đó như thế này:

bullet = new Bullet(direction, point); 

Tuy nhiên, đó chặt cặp vợ chồng lớp PlayerShip đến lớp Bullet. Làm thế nào điều này nên làm việc dưới tiêm phụ thuộc? Tôi có cần phải tạo ra một giao diện BulletFactory và tiêm một thực hiện đó vào con tàu không?

Chỉnh sửa: Tôi không thực sự viết tiểu hành tinh. Đây là một ví dụ đơn giản mà tôi nghĩ mọi người sẽ hiểu. Tôi muốn một cái gì đó mà cần thiết để được tạo ra một thời gian chạy (không phải trong khi "dây lên các đối tượng") mà cũng có các thông số để xây dựng nó.

Trả lời

3

Phụ thuộc nếu bạn chỉ có một loại dấu đầu dòng ...

Nếu chỉ một lần thì tôi sẽ nói bạn sẽ ổn.

Nhưng nếu bạn có một Bullet , DoubleBullet, PowerBullet, NukeBullet vv

Sau đó, tôi sẽ làm cho lớp cơ sở Bullet và tất cả các derrived khác từ nó

Sau đó, tôi sẽ làm cho nhà máy Bullet và nó sẽ có CreateBullet, CreatePowerBullet, v.v.

Câu hỏi còn lại sẽ là thứ gì khác tạo ra một viên đạn? Nếu như vậy thì tôi sẽ tạo ra một nhà máy để củng cố logic tạo ở một nơi ...

Nếu không nó có mùi giống như bạn sử dụng DI chỉ để được sử dụng DI ...

+0

Ngoài ra, nếu "bullet" chính nó là một đối tượng rất phức tạp với cây đối tượng riêng của nó, bạn có thể muốn một nhà máy để tránh tàu có phụ thuộc vào phụ thuộc của Bullet. – Epaga

1

Việc tiêm phụ thuộc không phù hợp cho trường hợp này. Nếu bạn tạo một nhà máy cho điều này, bạn sẽ lạm dụng các mẫu thiết kế. Bạn không thể tách rời toàn bộ hệ thống, trong trường hợp này, Ship có một thành phần với Bullet, và trong trường hợp bạn cần phức tạp hơn một mẫu khác (không nhất thiết là DI) có thể là đủ.

+1

Vì vậy, chỉ sử dụng DI cho các đối tượng loại dịch vụ và người độc thân? –

1

Vâng, đây có mùi giống như quá architecting . Tuy nhiên, ngoài đỉnh đầu của tôi, bạn có thể có một tài sản mà lưu trữ các loại đạn và sau đó có khuôn khổ DI của bạn (ninject ở đây) tạo ra viên đạn.

public Type BulletType {get; set;} 

public void fire() 
{ 
    var b = (BulletType) kernel.get(BulletType); 
    b.fire(point, direction); 
} 
+0

Vì vậy, kernel.get (BulletType) sẽ tra cứu tên lớp mà tôi đã chỉ định bên ngoài và tạo cho tôi một ví dụ về điều đó? Điều này có nghĩa là điểm và hướng không thể được truyền trong constructor nhưng phải được thiết lập tiếp theo để tạo ra? –

+0

Đúng, hạt nhân thực hiện tìm kiếm và tạo trong khung Ninject. Và nó không lấy các tham số như điểm. Đó có phải là vấn đề không? – Ray

2

Bạn đã nhận được khá nhiều. Nếu bạn muốn được tách riêng với lớp Bullet, thì theo ý kiến ​​của tôi, giải pháp tốt nhất là tiêm một nhà máy có thể tạo ra các đối tượng Bullet.

Lưu ý rằng bạn có nhiều mức độ gián tiếp bạn có thể thực hiện, mỗi cấp cho bạn linh hoạt hơn, nhưng yêu cầu nhiều mã hơn và có thể khó hiểu hơn. Cách đơn giản nhất là có BulletFactoryBullet cả hai đều là các loại cụ thể. Điều này có nghĩa là bạn không thể dễ dàng thực hiện các triển khai khác nhau của chúng, nhưng bạn vẫn có thể mở rộng cả hai và chuyển vào một lớp con của BulletFactory trả về các lớp con của Bullet. Nếu mục đích duy nhất của bạn cho tiêm là để làm cho bài kiểm tra đơn vị dễ dàng hơn, đây là con đường tôi sẽ mất. Tất nhiên, bạn cũng có thể tạo BulletFactory giao diện hoặc Bullet giao diện hoặc cả hai. Nếu bạn định thực hiện các mục đích khác nhau cho mục đích không thử nghiệm, đây là tuyến đường tôi sẽ thực hiện.

Cuối cùng, bạn phải quyết định xem lợi ích của việc tách lớp Bullet khỏi lớp học PlayerShip có đáng không. Khớp nối chặt chẽ không phải là điều ác và không nên tránh bằng mọi giá — nó có ý nghĩa trong một số ngữ cảnh, chứ không phải ở những ngữ cảnh khác. Chỉ có kinh nghiệm sẽ giúp bạn tìm ra khi nào cần cặp lớp và khi nào thì tách chúng ra.

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