Chắc chắn, nhưng chúng tôi gọi đó là thành phần và đoàn . Mô hình chiến lược và tiêm phụ thuộc có thể có cấu trúc tương tự nhau nhưng ý định của chúng là khác nhau.
Mẫu chiến lược cho phép sửa đổi thời gian chạy của hành vi trong cùng một giao diện. Tôi có thể bảo một con vịt trời biết bay và xem nó bay bằng đôi cánh. Sau đó đổi nó lấy một con vịt phi công phản lực và xem nó bay với các hãng hàng không Delta. Làm điều đó trong khi chương trình đang chạy là một điều Chiến lược mẫu.
Dependency Injection là một kỹ thuật để tránh phụ thuộc mã hóa cứng để họ có thể thay đổi độc lập mà không yêu cầu khách hàng phải sửa đổi khi họ thay đổi. Khách hàng chỉ đơn giản là bày tỏ nhu cầu của họ mà không biết họ sẽ được đáp ứng như thế nào. Do đó, làm thế nào chúng được đáp ứng được quyết định ở nơi khác (thường là chính). Bạn không cần hai con vịt để sử dụng kỹ thuật này. Chỉ cần một cái gì đó sử dụng một con vịt mà không biết hoặc quan tâm con vịt nào. Một cái gì đó không xây dựng con vịt hoặc đi tìm nó nhưng hoàn toàn hạnh phúc khi sử dụng bất cứ con vịt nào bạn đưa nó.
Nếu tôi có một lớp vịt cụ thể, tôi có thể cho nó thực hiện hành vi bay. Tôi thậm chí có thể khiến nó chuyển đổi các hành vi từ fly-with-wing sang fly-with-Delta dựa trên một biến trạng thái. Biến mà có thể là một boolean, một int, hoặc nó có thể là một FlyBehavior
mà có một fly
phương pháp mà không bất cứ phong cách bay mà không có tôi phải thử nghiệm nó với một nếu. Bây giờ tôi có thể thay đổi kiểu bay mà không cần thay đổi loại vịt. Bây giờ Mallards có thể trở thành phi công. Đây là thành phần và đoàn . Con vịt bao gồm một FlyBehavior và nó có thể ủy thác các yêu cầu bay cho nó. Bạn có thể thay thế tất cả các hành vi vịt của bạn cùng một lúc theo cách này hoặc giữ một cái gì đó cho mỗi hành vi hoặc bất kỳ sự kết hợp nào ở giữa.
Điều này cung cấp cho bạn tất cả các quyền hạn mà thừa kế có ngoại trừ một. Kế thừa cho phép bạn thể hiện phương thức Vịt nào bạn ghi đè trong các kiểu con Vịt. Thành phần và ủy quyền yêu cầu Vịt phải ủy quyền rõ ràng cho các kiểu con ngay từ đầu. Điều này linh hoạt hơn nhiều nhưng nó liên quan đến việc gõ bàn phím nhiều hơn và Duck phải biết điều đó đang xảy ra.
Tuy nhiên, nhiều người tin rằng sự kế thừa phải được thiết kế rõ ràng ngay từ đầu. Và nếu không, bạn nên đánh dấu các lớp của mình là niêm phong / cuối cùng để không cho phép thừa kế. Nếu bạn có quan điểm đó thì sự kế thừa thực sự không có lợi thế hơn so với thành phần và sự ủy nhiệm. Bởi vì sau đó, dù bằng cách nào bạn cũng phải thiết kế để mở rộng ngay từ đầu hoặc sẵn sàng xé mọi thứ sau này.
Xé mọi thứ thực sự là một lựa chọn phổ biến. Chỉ cần lưu ý rằng có những trường hợp đó là một vấn đề. Nếu bạn đã triển khai độc lập các thư viện hoặc mô-đun mã mà bạn không có ý định cập nhật với bản phát hành tiếp theo, bạn có thể sẽ gặp khó khăn khi xử lý các phiên bản của các lớp không biết gì về những gì bạn sắp làm.
Mặc dù sẵn sàng xé mọi thứ sau này có thể giải phóng bạn khỏi việc thiết kế, có một điều rất mạnh mẽ về việc có thể thiết kế một cái gì đó sử dụng một con vịt mà không cần phải biết con vịt sẽ thực sự làm gì khi sử dụng. Điều đó không biết là công cụ mạnh mẽ. Nó cho phép bạn ngừng suy nghĩ về vịt trong một thời gian và suy nghĩ về phần còn lại của mã của bạn.
"Chúng ta có thể" và "chúng ta nên" là những câu hỏi khác nhau. Thành phần ủng hộ thừa kế không nói không bao giờ sử dụng thừa kế. Vẫn có những trường hợp thừa kế có ý nghĩa nhất. Tôi sẽ chỉ cho bạn ví dụ yêu thích của tôi :
public class LoginFailure : System.ApplicationException {}
Kế thừa cho phép bạn tạo các ngoại lệ với các tên mô tả cụ thể hơn chỉ trong một dòng.
Hãy thử làm điều đó với thành phần và bạn sẽ nhận được một mớ hỗn độn. Ngoài ra, không có rủi ro về vấn đề thừa kế yo-yo vì không có dữ liệu hoặc phương pháp nào ở đây để tái sử dụng và khuyến khích chuỗi kế thừa. Tất cả điều này thêm là một tên tốt. Đừng bao giờ đánh giá thấp giá trị của một cái tên hay.
Duckbehavior.quackBehavior
và các lĩnh vực khác 'trong mã của bạn là gì?