为了账号安全,请及时绑定邮箱和手机立即绑定

“编程到接口,而不是实现”意味着什么?

“编程到接口,而不是实现”意味着什么?

互换的青春 2019-07-03 15:45:48
“编程到接口,而不是实现”意味着什么?在阅读有关设计模式的文章时,人们会无意中发现这个短语。但我不明白,有人能给我解释一下吗?
查看完整描述

3 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞


接口只是契约或签名,他们对实现一无所知。

针对接口进行编码意味着,客户端代码始终保存一个由工厂提供的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}


这只是一个基本的例子,对这个原则的实际解释超出了这个答案的范围。

编辑

我已经更新了上面的例子,并添加了一个抽象的扬声器基类。在这个更新中,我添加了一个功能到所有的斯皮克,以“打个招呼”。所有发言者都说“你好世界”。因此,这是一个具有类似功能的共同特性。参考类图,您会发现Speer抽象类实现了ISpeaker接口,并将Talk()标记为抽象,这意味着每个扬声器实现都负责实现Talk方法,因为它因说话人而异。但所有发言者都一致表示“你好”。因此,在抽象的扬声器类中,我们定义了一个方法,该方法表示“HelloWorld”,每个扬声器实现都将派生出SayHello方法。

考虑一种情况,在这种情况下,西班牙语发言人不能说你好,所以在这种情况下,您可以覆盖对西班牙语发言人的SayHello方法,并提出适当的例外。

请注意,我们没有对InterfaceISpeaker做任何更改。客户端代码和SpeakerFactory也保持不变。这就是我们通过编程到接口.

我们可以通过在每个实现中添加一个基类、抽象类、说话人和一些小修改来实现这种行为,从而使原始程序保持不变。这是任何应用程序都需要的特性,它使您的应用程序易于维护。

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}



查看完整回答
反对 回复 2019-07-03
?
HUH函数

TA贡献1836条经验 获得超4个赞

将接口看作对象与其客户端之间的契约。即接口指定对象可以做的事情,以及访问这些事情的签名。

实现是实际的行为。例如,您有一个方法sort()。您可以实现快速排序或MergeSort。这对于调用排序的客户端代码来说并不重要,只要接口不改变。

像JavaAPI和.NET Framework这样的库大量使用接口,因为数百万程序员使用所提供的对象。这些库的创建者必须非常小心,不要将接口更改为这些库中的类,因为它会影响所有使用库的程序员。另一方面,他们可以任意更改实现。

如果作为程序员,您可以针对实现进行代码编写,那么一旦它更改,您的代码就会停止工作。因此,以这种方式考虑界面的好处:

  1. 它隐藏了不需要知道的东西,使对象更易于使用。
  2. 它提供了对象将如何运行的契约,因此您可以依赖于此。


查看完整回答
反对 回复 2019-07-03
  • 3 回答
  • 0 关注
  • 715 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信