Пожалуйста, прости меня за псевдокод заранее!
Читайте о принципах SOLID. В принципах SOLID для использования интерфейсов есть несколько причин. Интерфейсы позволяют вам отделить ваши зависимости от реализации. Вы можете сделать еще один шаг вперед, используя такой инструмент, как StructureMap, чтобы действительно растопить муфту.
Где вы могли бы привыкнуть к
Widget widget1 = new Widget;
Это конкретно говорит о том, что вы хотите создать новый экземпляр Widget. Однако, если вы делаете это внутри метода другого объекта, вы теперь говорите, что другой объект напрямую зависит от использования Widget. Таким образом, мы могли бы тогда сказать что-то вроде
public class AnotherObject
{
public void SomeMethod(Widget widget1)
{
//..do something with widget1
}
}
Мы все еще привязаны к использованию Widget здесь. Но, по крайней мере, это более тестируемо, поскольку мы можем внедрить реализацию Widget в SomeMethod. Теперь, если бы мы вместо этого использовали Интерфейс, мы могли бы еще больше отделить вещи.
public class AnotherObject
{
public void SomeMethod(IWidget widget1)
{
//..do something with widget1
}
}
Обратите внимание, что теперь нам не требуется конкретная реализация Widget, а вместо этого мы запрашиваем все, что соответствует интерфейсу IWidget. Это означает, что все может быть внедрено, что означает, что при повседневном использовании кода мы можем внедрить фактическую реализацию Widget. Но это также означает, что когда мы хотим протестировать этот код, мы можем внедрить поддельную / mock / stub (в зависимости от вашего понимания этих терминов) и протестировать наш код.
Но как мы можем пойти дальше? С помощью StructureMap мы можем еще больше отделить этот код. В последнем примере кода наш код вызова может выглядеть примерно так
public class AnotherObject
{
public void SomeMethod(IWidget widget1)
{
//..do something with widget1
}
}
public class CallingObject
{
public void AnotherMethod()
{
IWidget widget1 = new Widget();
new AnotherObject().SomeMethod(widget1);
}
}
Как вы можете видеть в приведенном выше коде, мы удалили зависимость в SomeMethod, передав объект, который соответствует IWidget. Но в CallingObject (). AnotherMethod у нас все еще есть зависимость. Мы также можем использовать StructureMap для удаления этой зависимости!
[PluginFamily("Default")]
public interface IAnotherObject
{
...
}
[PluginFamily("Default")]
public interface ICallingObject
{
...
}
[Pluggable("Default")]
public class AnotherObject : IAnotherObject
{
private IWidget _widget;
public AnotherObject(IWidget widget)
{
_widget = widget;
}
public void SomeMethod()
{
//..do something with _widget
}
}
[Pluggable("Default")]
public class CallingObject : ICallingObject
{
public void AnotherMethod()
{
ObjectFactory.GetInstance<IAnotherObject>().SomeMethod();
}
}
Обратите внимание, что нигде в приведенном выше коде мы не реализуем фактическую реализацию AnotherObject. Поскольку все связано с StructurMap, мы можем позволить StructureMap передавать соответствующие реализации в зависимости от того, когда и где выполняется код. Теперь код по-настоящему гибок в том, что мы можем указать через конфигурацию или программно в тесте, какую реализацию мы хотим использовать. Эта конфигурация может быть выполнена на лету или как часть процесса сборки и т. Д. Но ее не нужно нигде жестко подключать.