Sự phụ thuộc đảo ngược trong OOP có nghĩa là bạn mã hóa một giao diện mà sau đó được cung cấp bởi một triển khai trong một đối tượng.
Các ngôn ngữ hỗ trợ các chức năng ngôn ngữ cao hơn thường có thể giải quyết các vấn đề đảo ngược phụ thuộc đơn giản bằng cách chuyển hành vi dưới dạng hàm thay vì một đối tượng thực hiện giao diện theo nghĩa OO.
Trong các ngôn ngữ như vậy, chữ ký của hàm có thể trở thành giao diện và một hàm được truyền vào thay vì một đối tượng truyền thống để cung cấp hành vi mong muốn. Lỗ hổng trong mẫu giữa là một ví dụ tốt cho điều này.
Nó cho phép bạn đạt được kết quả tương tự với ít mã hơn và biểu cảm hơn, vì bạn không cần phải thực hiện cả một lớp phù hợp với giao diện (OOP) để cung cấp hành vi mong muốn cho người gọi. Thay vào đó, bạn chỉ có thể vượt qua một định nghĩa hàm đơn giản. Tóm lại: Mã thường dễ bảo trì hơn, biểu cảm hơn và linh hoạt hơn khi người ta sử dụng các hàm bậc cao hơn.
Một ví dụ trong C #
Cách tiếp cận truyền thống:
public IEnumerable<Customer> FilterCustomers(IFilter<Customer> filter, IEnumerable<Customers> customers)
{
foreach(var customer in customers)
{
if(filter.Matches(customer))
{
yield return customer;
}
}
}
//now you've got to implement all these filters
class CustomerNameFilter : IFilter<Customer> /*...*/
class CustomerBirthdayFilter : IFilter<Customer> /*...*/
//the invocation looks like this
var filteredDataByName = FilterCustomers(new CustomerNameFilter("SomeName"), customers);
var filteredDataBybirthDay = FilterCustomers(new CustomerBirthdayFilter(SomeDate), customers);
Với các chức năng bậc cao hơn:
public IEnumerable<Customer> FilterCustomers(Func<Customer, bool> filter, IEnumerable<Customers> customers)
{
foreach(var customer in customers)
{
if(filter(customer))
{
yield return customer;
}
}
}
Bây giờ việc thực hiện và gọi trở nên ít cồng kềnh hơn. Chúng tôi không cần phải cung cấp triển khai IFilter nữa. Chúng ta không cần phải thực hiện các lớp cho các bộ lọc nữa.
var filteredDataByName = FilterCustomers(x => x.Name.Equals("CustomerName"), customers);
var filteredDataByBirthday = FilterCustomers(x => x.Birthday == SomeDateTime, customers);
Tất nhiên, điều này đã có thể được LinQ thực hiện trong C #. Tôi chỉ sử dụng ví dụ này để minh họa rằng việc sử dụng các hàm bậc cao hơn thay vì các đối tượng thực hiện giao diện sẽ dễ dàng và linh hoạt hơn.