面向接口编程的详细说明(二)-编程实例

电脑杂谈  发布时间:2020-05-03 17:21:18  来源:网络整理

面向编程编程思想_swift面向协议编程_面向接口编程

通过上一篇文章的讨论,我认为朋友对“面对面的界面编程”有一个大致的了解. 因此,在本文中,我们将通过一个示例使您直观地了解这一重要的编程思想. 为了充分考虑初学者,这个例子很简单,希望您能原谅我.

提出的问题

定义: 现在我们要开发一个模拟移动存储设备读写的应用程序,即计算机与U盘,MP3和移动硬盘之类的设备交换数据.

上下文(环境): 已知要实现三种移动存储设备,例如U盘,MP3播放器和移动硬盘,这需要计算机与这三种设备交换数据,并且可能会有新的第三方移动存储设备,因此计算机必须是可扩展的,并且能够与当前未知且将来可能出现的存储设备交换数据. 读和写的实现方法在存储设备之间是不同的. U盘和移动硬盘只有两种方法. MP3Player也具有PlayMusic方法.

名词定义: 数据交换= {读,写}

看到上述问题,我认为您必须有很多想法. 这是一个非常好的问题,很多解决方案都可以达到目的. 下面,我列出了一些典型的解决方案.

解决方案列表

解决方案1: 定义三个类: FlashDisk,MP3Player和MobileHardDisk,并实现各自的Read和Write方法. 然后在Computer类中实例化以上三个类,并为每个类编写读写方法. 例如,为FlashDisk写ReadFromFlashDisk和WriteToFlashDisk. 总共有六种方法.

解决方案2: 定义抽象类MobileStorage并在其中编写虚拟方法Read和Write. 这三个存储设备继承了这个抽象类,并重写了Read和Write方法. Computer类包含一个类型为MobileStorage的成员变量,并为其编写一个get / set设备,因此Computer中仅需要两种方法: ReadData和WriteData,以及通过多态性来读写不同的移动设备.

解决方案3: 除了未定义抽象类,而是定义了IMobileStorage接口,并且移动存储类实现了此接口,与解决方案2基本相同. 计算机依靠IMobileStorage接口实现多态.

解决方案4: 定义接口IReadable和IWritable. 这两个接口分别仅包含读取和写入,然后定义接口IMobileStorage接口以从IReadable和IWritable继承. 其余实施与方案3相同.

接下来,让我们分析以上四种方案:

面向编程编程思想_swift面向协议编程_面向接口编程

首先,第一个解决方案是最直接,最简单的实现,但是它具有致命的弱点: 可伸缩性差. 换句话说,它不符合“开放-封闭原则”(注: 表示可扩展,不可修改). 如果将来有第三方扩展移动存储设备可用,则必须修改计算机. 这就像在实际计算机上为每种类型的移动存储设备实现不同的插槽,并具有自己的驱动程序一样. 当我们有一个新的移动存储设备时,我们必须将计算机卸载八块,然后添加一个新的插槽,并为该新设备编写一组驱动程序. 这种设计显然是不可取的.

该解决方案的另一个缺点是存在许多冗余代码. 如果有100种移动存储,是否有必要在我们的计算机中编写至少200种方法?这是不可接受的!

让我们再次看一下方案二和方案三. 之所以将这两种方案一起讨论是因为它们本质上是一种方案(就思想而言),但是实现方式不同,一种是使用抽象,一种是接口,最终目的应该是一样.

让我们首先评估该解决方案: 首先,它解决了代码冗余的问题,因为移动设备可以动态替换,并且它们都实现一个公共接口,所以无论有多少移动设备,只要有一个Read方法和一个Write方法,多态将帮助我们解决问题. 对于第一个问题,由于可以在运行时动态替换它,而不必在Computer中对移动存储类进行硬编码,因此,使用新的第三方设备,就可以完全替换并运行它. 这就是所谓的“依赖于接口,而不是依赖于特定的类”. 我不相信你看看. Computer类只有一个类型为MobileStorage或IMobileStorage的成员变量. 至于该变量的具体类型,它不知道,取决于我们在运行时分配此变量. 结果,大大降低了计算机与移动存储器之间的耦合程度.

那么我应该在这里选择一个抽象类或一个接口吗?还记得我在第一篇文章中关于抽象类和接口的选择的建议吗?看一下动机. 在这里,我们的动机显然是实现多态而不是代码重用,因此我们当然必须使用接口.

最后,让我们看一下解决方案四,它与解决方案三非常相似,只是将“可读”和“可写”这两个规则抽象为接口,并且IMobileStorage继承了它们. 这样做显然会进一步增加灵活性,但是是否有过度设计的嫌疑?我的观点是: 这取决于具体情况. 如果我们的应用程序中可能有一些类,这些类仅实现read方法或仅实现write方法,例如只读CD,那么这也是可能的. 如果我们知道将来将要出现的所有内容都可以读写,那么这两个接口是不必要的. 实际上,如果将只读设备的Write方法保留为空白或引发异常,则也可以消除这两个接口. 一言以蔽之: 理论已经死了,人们还活着,一切都来自现实的需要,既要防止设计不足,又要防止过度设计.

在这里,我们暂时认为将来所有的移动存储都可以读写,因此我们选择选项三.

实施

接下来,我们将实施解决方案. 我选择的语言是C#,但是代码中没有使用C#的独特性,因此使用其他语言的朋友也可以参考它.

首先编写IMobileStorage接口:

namespace InterfaceExample
{
    public interface IMobileStorage
    {
        void Read();//从自身读数据
        void Write();//将数据写入自身
    }
}

代码相对简单,只有两种方法,无话可说,接下来是三种移动存储设备的具体实现代码:

swift面向协议编程_面向接口编程_面向编程编程思想

U盘

namespace InterfaceExample
{
    public class FlashDisk : IMobileStorage
    {
        public void Read()
        {
            Console.WriteLine("Reading from FlashDisk……");
            Console.WriteLine("Read finished!");
        }
        public void Write()
        {
            Console.WriteLine("Writing to FlashDisk……");
            Console.WriteLine("Write finished!");
        }
    }
}

MP3

namespace InterfaceExample
{
    public class MP3Player : IMobileStorage
    {
        public void Read()
        {
            Console.WriteLine("Reading from MP3Player……");
            Console.WriteLine("Read finished!");
        }
        public void Write()
        {
            Console.WriteLine("Writing to MP3Player……");
            Console.WriteLine("Write finished!");
        }
        public void PlayMusic()
        {
            Console.WriteLine("Music is playing……");
        }
    }
}

可移动硬盘

namespace InterfaceExample
{
    public class MobileHardDisk : IMobileStorage
    {
        public void Read()
        {
            Console.WriteLine("Reading from MobileHardDisk……");
            Console.WriteLine("Read finished!");
        }
        public void Write()
        {
            Console.WriteLine("Writing to MobileHardDisk……");
            Console.WriteLine("Write finished!");
        }
    }
}

如您所见,它们都实现了IMobileStorage接口,并重写了各自不同的Read和Write方法. 接下来,让我们写计算机:

namespace InterfaceExample
{
    public class Computer
    {
        private IMobileStorage _usbDrive;
        public IMobileStorage UsbDrive
        {
            get
            {
                return this._usbDrive;
            }
            set
            {
                this._usbDrive = value;
            }
        }
        public Computer()
        {
        }
        public Computer(IMobileStorage usbDrive)
        {
            this.UsbDrive = usbDrive;
        }
    
        public void ReadData()
        {
            this._usbDrive.Read();
        }
        public void WriteData()
        {
            this._usbDrive.Write();
        }
    }
}

UsbDrive是可更换的移动存储设备. 该名称使每个人都感觉直观,就像我们通常使用计算机上的USB插座来插拔设备一样.

好!让我们测试一下我们的“计算机”和“可移动存储设备”是否正常运行. 我正在使用C#控制台程序,具体代码如下:

namespace InterfaceExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Computer computer = new Computer();
            IMobileStorage mp3Player = new MP3Player();
            IMobileStorage flashDisk = new FlashDisk();
            IMobileStorage mobileHardDisk = new MobileHardDisk();
            Console.WriteLine("I inserted my MP3 Player into my computer and copy some music to it:");
            computer.UsbDrive = mp3Player;
            computer.WriteData();
            Console.WriteLine();
            Console.WriteLine("Well,I also want to copy a great movie to my computer from a mobile hard disk:");
            computer.UsbDrive = mobileHardDisk;
            computer.ReadData();
            Console.WriteLine();
            Console.WriteLine("OK!I have to read some files from my flash disk and copy another file to it:");
            computer.UsbDrive = flashDisk;
            computer.ReadData();
            computer.WriteData();
            Console.ReadLine();
        }
    }
}


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-197813-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 献文帝
      献文帝

      粗粮还有真货吗

    • 郑子玉
      郑子玉

      除非对方并不是通过而是在上面逗留或作出危害你家安全的事情

    • 孟迟
      孟迟

      不过

    热点图片
    拼命载入中...