Интерфейсы - это просто контракты или подписи, и они не знают
что-нибудь о реализациях.
Кодирование по интерфейсу означает, что клиентский код всегда содержит объект интерфейса, предоставленный фабрикой. Любой экземпляр, возвращаемый фабрикой, будет иметь тип Interface, который должен быть реализован любым классом-кандидатом фабрики. Таким образом, клиентская программа не беспокоится о реализации, и сигнатура интерфейса определяет, какие все операции могут быть выполнены. Это может быть использовано для изменения поведения программы во время выполнения. Это также помогает вам писать гораздо лучшие программы с точки зрения обслуживания.
Вот базовый пример для вас.
public enum Language
{
English, German, Spanish
}
public class SpeakerFactory
{
public static ISpeaker CreateSpeaker(Language language)
{
switch (language)
{
case Language.English:
return new EnglishSpeaker();
case Language.German:
return new GermanSpeaker();
case Language.Spanish:
return new SpanishSpeaker();
default:
throw new ApplicationException("No speaker can speak such language");
}
}
}
[STAThread]
static void Main()
{
//This is your client code.
ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
speaker.Speak();
Console.ReadLine();
}
public interface ISpeaker
{
void Speak();
}
public class EnglishSpeaker : ISpeaker
{
public EnglishSpeaker() { }
#region ISpeaker Members
public void Speak()
{
Console.WriteLine("I speak English.");
}
#endregion
}
public class GermanSpeaker : ISpeaker
{
public GermanSpeaker() { }
#region ISpeaker Members
public void Speak()
{
Console.WriteLine("I speak German.");
}
#endregion
}
public class SpanishSpeaker : ISpeaker
{
public SpanishSpeaker() { }
#region ISpeaker Members
public void Speak()
{
Console.WriteLine("I speak Spanish.");
}
#endregion
}
Это просто базовый пример и
Фактическое объяснение принципа
выходит за рамки этого ответа.
EDIT
Я обновил приведенный выше пример и добавил абстрактный базовый класс Speaker. В этом обновлении я добавил функцию для всех Спикеров в «SayHello». Все выступающие говорят «Hello World». Так что это общая черта с похожей функцией. Обратитесь к диаграмме классов, и вы обнаружите, что абстрактный класс Speaker реализует интерфейс ISpeaker и помечает Speak () как абстрактный, что означает, что каждая реализация Speaker отвечает за реализацию метода Speak, поскольку он варьируется от Speaker к Speaker. Но все ораторы говорят «Привет» единогласно. Поэтому в абстрактном классе Speaker мы определяем метод, который говорит «Hello World», и каждая реализация Speaker будет получать метод SayHello.
Рассмотрим случай, когда SpanishSpeaker не может Say Hello, поэтому в этом случае вы можете переопределить метод SayHello для испанского языка и вызвать соответствующее исключение.
Обратите внимание, что у нас есть
не внесены какие-либо изменения в интерфейс
ISpeaker. И клиентский код и
SpeakerFactory также остаются без изменений
без изменений. И это то, что мы достигаем с помощью Programming to Interface .
И мы могли бы добиться этого, просто добавив базовый абстрактный класс Speaker и некоторые незначительные изменения в каждой реализации, таким образом, оставив исходную программу без изменений. Это желаемая функция любого приложения, и оно делает ваше приложение легко обслуживаемым.
public enum Language
{
English, German, Spanish
}
public class SpeakerFactory
{
public static ISpeaker CreateSpeaker(Language language)
{
switch (language)
{
case Language.English:
return new EnglishSpeaker();
case Language.German:
return new GermanSpeaker();
case Language.Spanish:
return new SpanishSpeaker();
default:
throw new ApplicationException("No speaker can speak such language");
}
}
}
class Program
{
[STAThread]
static void Main()
{
//This is your client code.
ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
speaker.Speak();
Console.ReadLine();
}
}
public interface ISpeaker
{
void Speak();
}
public abstract class Speaker : ISpeaker
{
#region ISpeaker Members
public abstract void Speak();
public virtual void SayHello()
{
Console.WriteLine("Hello world.");
}
#endregion
}
public class EnglishSpeaker : Speaker
{
public EnglishSpeaker() { }
#region ISpeaker Members
public override void Speak()
{
this.SayHello();
Console.WriteLine("I speak English.");
}
#endregion
}
public class GermanSpeaker : Speaker
{
public GermanSpeaker() { }
#region ISpeaker Members
public override void Speak()
{
Console.WriteLine("I speak German.");
this.SayHello();
}
#endregion
}
public class SpanishSpeaker : Speaker
{
public SpanishSpeaker() { }
#region ISpeaker Members
public override void Speak()
{
Console.WriteLine("I speak Spanish.");
}
public override void SayHello()
{
throw new ApplicationException("I cannot say Hello World.");
}
#endregion
}