Давайте проиллюстрируем это следующим кодом:
namespace ExperimentConsoleApp
{
class Program
{
static void Main()
{
ILogger loggerA = new DatabaseLogger();
ILogger loggerB = new FileLogger();
loggerA.Log("My message");
loggerB.Log("My message");
}
}
public interface ILogger
{
void Log(string message);
}
public class DatabaseLogger : ILogger
{
public void Log(string message)
{
// Log to database
}
}
public class FileLogger : ILogger
{
public void Log(string message)
{
// Log to File
}
}
}
Предположим, что вы Logger
разработчик, а разработчику приложения требуется Logger
от вас. Вы предоставляете разработчику приложения свой ILogger
интерфейс и говорите ему, что он может использовать, но ему не нужно беспокоиться о деталях реализации.
После этого вы начинаете разработку FileLogger
и Databaselogger
и убедитесь, что они следуют интерфейсу, который вы дали разработчику приложения.
Разработчик приложения теперь разрабатывает интерфейс, а не реализацию. Он не знает или не заботится о том, как реализован класс. Он знает только интерфейс. Это способствует меньшей связности кода и дает вам возможность (например, через файлы конфигурации) легко переключаться на другую реализацию.