Инверсия зависимости в ООП означает, что вы кодируете интерфейс, который затем предоставляется реализацией в объекте.
Языки, которые поддерживают функции более высокого языка, часто могут решить простые проблемы инверсии зависимостей, передавая поведение как функцию вместо объекта, который реализует интерфейс в ОО-смысле.
В таких языках подпись функции может стать интерфейсом, и вместо традиционного объекта передается функция для обеспечения желаемого поведения. Отверстие в среднем узоре является хорошим примером для этого.
Это позволит вам достичь того же результата с меньшим количеством кода и большей выразительностью, поскольку вам не нужно реализовывать целый класс, соответствующий интерфейсу (OOP), чтобы обеспечить желаемое поведение для вызывающей стороны. Вместо этого вы можете просто передать простое определение функции. Вкратце: код часто легче поддерживать, он более выразителен и более гибок, когда используются функции более высокого порядка.
Пример в C #
Традиционный подход:
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);
С функциями высшего порядка:
public IEnumerable<Customer> FilterCustomers(Func<Customer, bool> filter, IEnumerable<Customers> customers)
{
foreach(var customer in customers)
{
if(filter(customer))
{
yield return customer;
}
}
}
Теперь реализация и вызов становятся менее громоздкими. Нам больше не нужно предоставлять реализацию IFilter. Нам больше не нужно реализовывать классы для фильтров.
var filteredDataByName = FilterCustomers(x => x.Name.Equals("CustomerName"), customers);
var filteredDataByBirthday = FilterCustomers(x => x.Birthday == SomeDateTime, customers);
Конечно, это уже может быть сделано LinQ в C #. Я просто использовал этот пример, чтобы проиллюстрировать, что проще и более гибко использовать функции более высокого порядка вместо объектов, которые реализуют интерфейс.