2022年面向接口编程详解 .pdf

上传人:Q****o 文档编号:31702680 上传时间:2022-08-08 格式:PDF 页数:24 大小:1.35MB
返回 下载 相关 举报
2022年面向接口编程详解 .pdf_第1页
第1页 / 共24页
2022年面向接口编程详解 .pdf_第2页
第2页 / 共24页
点击查看更多>>
资源描述

《2022年面向接口编程详解 .pdf》由会员分享,可在线阅读,更多相关《2022年面向接口编程详解 .pdf(24页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、面向接口编程详解(一)思想基础我想,对于各位使用面向对象编程语言的程序员来说,“接口”这个名词一定不陌生,但是不知各位有没有这样的疑惑:接口有什么用途?它和抽象类有什么区别?能不能用抽象类代替接口呢?而且,作为程序员,一定经常听到“面向接口编程”这个短语,那么它是什么意思?有什么思想内涵?和面向对象编程是什么关系?本文将一一解答这些疑问。1. 面向接口编程和面向对象编程是什么关系首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思想体系,属于其一部分。或者说,它是面向对象编程体系中的思想精髓之一。2. 接口的本质接口,在表面上是由

2、几个没有主体代码的方法定义组成的集合体,有唯一的名称,可以被类或其他接口所实现(或者也可以说继承)。它在形式上可能是如下的样子:interface InterfaceName void Method1(); void Method2( int para1); void Method3( string para2,string para3); 那么,接口的本质是什么呢?或者说接口存在的意义是什么。我认为可以从以下两个视角考虑: 1 )接口是一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则。体现了自然界“如果你是 , 则必须能 , ”的理念。名师资料总结 - - -精品资料欢迎下载

3、- - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 24 页 - - - - - - - - - 例如,在自然界中,人都能吃饭,即“如果你是人,则必须能吃饭”。那么模拟到计算机程序中,就应该有一个IPerson (习惯上,接口名由“ I ”开头)接口,并有一个方法叫 Eat(),然后我们规定,每一个表示“人”的类,必须实现IPerson接口,这就模拟了自然界“如果你是人,则必须能吃饭”这条规则。从这里,我想各位也能看到些许面向对象思想的东西。面向对象思想的核心之一,就是模拟真实世界,把真实世界中的事物抽象成类,整个程

4、序靠各个类的实例互相通信、互相协作完成系统功能,这非常符合真实世界的运行状况,也是面向对象思想的精髓。2)接口是在一定粒度视图上同类事物的抽象表示。注意这里我强调了在一定粒度视图上,因为“同类事物”这个概念是相对的,它因为粒度视图不同而不同。例如,在我的眼里,我是一个人,和一头猪有本质区别,我可以接受我和我同学是同类这个说法,但绝不能接受我和一头猪是同类。但是,如果在一个动物学家眼里,我和猪应该是同类,因为我们都是动物,他可以认为“人”和“猪”都实现了IAnimal这个接口,而他在研究动物行为时,不会把我和猪分开对待,而会从“动物”这个较大的粒度上研究,但他会认为我和一棵树有本质区别。现在换了

5、一个遗传学家,情况又不同了,因为生物都能遗传,所以在他眼里,我不仅和猪没区别,和一只蚊子、一个细菌、一颗树、一个蘑菇乃至一个SARS病毒都没什么区别,因为他会认为我们都实现了IDescendable这个接口(注:descend vi. 遗传),即我们都是可遗传的东西,他不会分别研究我们,而会将所有生物作为同类进行研究,在他眼里没有人和病毒之分,只有可遗传的物质和不可遗传的物质。但至少,我和一块石头还是有区别的。可不幸的事情发生了,某日,地球上出现了一位伟大的人,他叫列宁,他在熟读马克思、恩格斯的辩证唯物主义思想巨著后,颇有心得,于是他下了一个著名的定义:所谓物质,就是能被意识所反映的客观实在。

6、至此,我和一块石头、一丝空气、一条成语和传输手机信号的电磁场已经没什么区别了,因为在列宁的眼里,我们都是可以被意识所反映的客观实在。如果列宁是一名程序员,他会这么说:所谓物质,就是所有同时实现了“IReflectabe ”和“IEsse”两个接口的类所生成的实例。(注:reflect v. 反映 esse n. 客观实在)也许你会觉得我上面的例子像在瞎掰,但是,这正是接口得以存在的意义。面向对名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 24 页 - - - - - -

7、 - - - 事物不加区别的对待而统一处理。而之所以敢这样做,就是因为有接口的存在。像那个遗传学家,他明白所有生物都实现了IDescendable接口,那只要是生物,一定有Descend()这个方法,于是他就可以统一研究,而不至于分别研究每一种生物而最终累死。可能这里还不能给你一个关于接口本质和作用的直观印象。那么在后文的例子和对几个设计模式的解析中,你将会更直观体验到接口的内涵。3. 面向接口编程综述通过上文,我想大家对接口和接口的思想内涵有了一个了解,那么什么是面向接口编程呢?我个人的定义是:在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中

8、),而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类。这样做的好处是显而易见的,首先对系统灵活性大有好处。当下层需要改变时,只要接口及接口功能不变,则上层不用做任何修改。甚至可以在不改动上层代码时将下层整个替换掉,就像我们将一个WD的 60G硬盘换成一个希捷的160G的硬盘,计算机其他地方不用做任何改动,而是把原硬盘拔下来、新硬盘插上就行了,因为计算机其他部分不依赖具体硬盘,而只依赖一个IDE 接口,只要硬盘实现了这个接口,就可以替换上去。从这里看,程序中的接口和现实中的接口极为相似,所以我一直认为,接口(interface)这个词用的真是神似!使用接口

9、的另一个好处就是不同部件或层次的开发人员可以并行开工,就像造硬盘的不用等造CPU的,也不用等造显示器的,只要接口一致,设计合理,完全可以并行进行开发,从而提高效率。本篇文章先到这里。最后我想再啰嗦一句:面向对象的精髓是模拟现实,这也可以说是我这篇文章的灵魂。所以,多从现实中思考面向对象的东西,对提高系统分析设计能力大有脾益。下篇文章,我将用一个实例来展示接口编程的基本方法。而第三篇,我将解析经典设计模式中的一些面向接口编程思想,并解析一下.NET 分名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - -

10、 - - 第 3 页,共 24 页 - - - - - - - - - 对本文的补充:仔细看了各位的回复,非常高兴能和大家一起讨论技术问题。感谢给出肯定的朋友,也要感谢提出意见和质疑的朋友,这促使我更深入思考一些东西,希望能借此进步。在这里我想补充一些东西,以讨论一些回复中比较集中的问题。1. 关于“面向接口编程”中的“接口”与具体面向对象语言中“接口”两个词看到有朋友提出“面向接口编程”中的“接口”二字应该比单纯编程语言中的interface范围更大。我经过思考,觉得很有道理。这里我写的确实不太合理。我想,面向对象语言中的“接口”是指具体的一种代码结构,例如C#中用 interface关键字

11、定义的接口。而“面向接口编程”中的“接口”可以说是一种从软件架构的角度、从一个更抽象的层面上指那种用于隐藏具体底层类和实现多态性的结构部件。从这个意义上说,如果定义一个抽象类,并且目的是为了实现多态,那么我认为把这个抽象类也称为“接口”是合理的。但是用抽象类实现多态合理不合理?在下面第二条讨论。概括来说,我觉得两个“接口”的概念既相互区别又相互联系。“面向接口编程”中的接口是一种思想层面的用于实现多态性、提高软件灵活性和可维护性的架构部件,而具体语言中的“接口”是将这种思想中的部件具体实施到代码里的手段。2. 关于抽象类与接口看到回复中这是讨论的比较激烈的一个问题。很抱歉我考虑不周没有在文章中

12、讨论这个问题。我个人对这个问题的理解如下:如果单从具体代码来看,对这两个概念很容易模糊,甚至觉得接口就是多余的,因为单从具体功能来看,除多重继承外(C# ,Java 中),抽象类似乎完全能取代接口。但是,难道接口的存在是为了实现多重继承?当然不是。我认为,抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。所以,如果你在为某个地方该使用接口还是抽象类而犹豫不决时,那么可以想想你的动机是什么。看到有朋友对IPerson 这个接口的质疑,我个人的理解是,IPerson这个接口该不该名师资料总结 - - -精品资料欢迎下载 - - - - - - - - -

13、 - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 24 页 - - - - - - - - - Women 和 Man ,都继承 Person,而且 Women 和 Man绝大多数方法都相同,只有一个方法DoSomethingInWC()不同(例子比较粗俗,各位见谅),那么当然定义一个AbstractPerson抽象类比较合理,因为它可以把其他所有方法都包含进去,子类只定义DoSomethingInWC (),大大减少了重复代码量。但是,如果我们程序中的Women 和 Man两个类基本没有共同代码,而且有一个PersonHandle 类需要实例化他

14、们,并且不希望知道他们是男是女,而只需把他们当作人看待,并实现多态,那么定义成接口就有必要了。总而言之,接口与抽象类的区别主要在于使用的动机,而不在于其本身。而一个东西该定义成抽象类还是接口,要根据具体环境的上下文决定。再者, 我认为接口和抽象类的另一个区别在于,抽象类和它的子类之间应该是一般和特殊的关系,而接口仅仅是它的子类应该实现的一组规则。(当然,有时也可能存在一般与特殊的关系,但我们使用接口的目的不在这里)如,交通工具定义成抽象类,汽车、飞机、轮船定义成子类,是可以接受的,因为汽车、飞机、轮船都是一种特殊的交通工具。再譬如 Icomparable接口,它只是说,实现这个接口的类必须要可

15、以进行比较,这是一条规则。 如果 Car 这个类实现了Icomparable,只是说, 我们的 Car 中有一个方法可以对两个Car 的实例进行比较,可能是比哪辆车更贵,也可能比哪辆车更大,这都无所谓,但我们不能说“汽车是一种特殊的可以比较”,这在文法上都不通。面向接口编程详解(二)编程实例问题的提出定义:现在我们要开发一个应用,模拟移动存储设备的读写,即计算机与U盘、 MP3、移动硬盘等设备进行数据交换。上下文(环境):已知要实现U盘、 MP3播放器、移动硬盘三种移动存储设备,要求计算机能同这三种设备进行数据交换,并且以后可能会有新的第三方的移动存储设备,所以计算机必须有扩展性,能与目前未知

16、而以后可能会出现的存储设备进行数据交换。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 24 页 - - - - - - - - - 各个存储设备间读、写的实现方法不同,U盘和移动硬盘只有这两个方法,MP3Player 还有一个PlayMusic 方法。名词定义:数据交换= 读,写 看到上面的问题,我想各位脑子中一定有了不少想法,这是个很好解决的问题,很多方案都能达到效果。下面,我列举几个典型的方案。解决方案列举方案一:分别定义FlashDisk 、 MP3Player、

17、MobileHardDisk三个类,实现各自的Read 和 Write方法。 然后在 Computer 类中实例化上述三个类,为每个类分别写读、写方法。例如,为 FlashDisk写 ReadFromFlashDisk 、WriteToFlashDisk两个方法。总共六个方法。方案二:定义抽象类MobileStorage,在里面写虚方法Read 和 Write ,三个存储设备继承此抽象类,并重写Read 和 Write 方法。 Computer 类中包含一个类型为MobileStorage 的成员变量, 并为其编写get/set器,这样 Computer 中只需要两个方法:ReadData 和

18、 WriteData,并通过多态性实现不同移动设备的读写。方案三:与方案二基本相同,只是不定义抽象类,而是定义接口IMobileStorage,移动存储器类实现此接口。Computer 中通过依赖接口IMobileStorage实现多态性。方案四:定义接口IReadable和 IWritable,两个接口分别只包含Read和 Write ,然后定义接口IMobileStorage接口继承自IReadable 和 IWritable,剩下的实现与方案三相同。下面,我们来分析一下以上四种方案:首先,方案一最直白,实现起来最简单,但是它有一个致命的弱点:可扩展性差。或者说,不符合“开放- 关闭原则”

19、(注:意为对扩展开放,对修改关闭)。当将来有了第三方扩展移动存储设备时,必须对Computer 进行修改。这就如在一个真实的计算机上,为每一种移动存储设备实现一个不同的插口、并分别有各自的驱动程序。当有了一种新的移动存储设备后,我们就要将计算机大卸八块,然后增加一个新的插口,在编写一套针对此名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 24 页 - - - - - - - - - 此方案的另一个缺点在于,冗余代码多。如果有100 种移动存储,那我们的Computer 中

20、岂不是要至少写200 个方法,这是不能接受的!我们再来看方案二和方案三,之所以将这两个方案放在一起讨论,是因为他们基本是一个方案(从思想层面上来说),只不过实现手段不同,一个是使用了抽象类,一个是使用了接口,而且最终达到的目的应该是一样的。我们先来评价这种方案:首先它解决了代码冗余的问题,因为可以动态替换移动设备,并且都实现了共同的接口,所以不管有多少种移动设备,只要一个Read方法和一个Write方法,多态性就帮我们解决问题了。而对第一个问题,由于可以运行时动态替换,而不必将移动存储类硬编码在Computer 中,所以有了新的第三方设备,完全可以替换进去运行。这就是所谓的“依赖接口,而不是依

21、赖与具体类”,不信你看看,Computer 类只有一个 MobileStorage类型或 IMobileStorage类型的成员变量, 至于这个变量具体是什么类型,它并不知道,这取决于我们在运行时给这个变量的赋值。如此一来,Computer 和移动存储器类的耦合度大大下降。那么这里该选抽象类还是接口呢?还记得第一篇文章我对抽象类和接口选择的建议吗?看动机。这里,我们的动机显然是实现多态性而不是为了代码复用,所以当然要用接口。最后我们再来看一看方案四,它和方案三很类似,只是将“可读”和“可写”两个规则分别抽象成了接口,然后让IMobileStorage再继承它们。这样做,显然进一步提高了灵活性,

22、但是,这有没有设计过度的嫌疑呢?我的观点是:这要看具体情况。如果我们的应用中可能会出现一些类,这些类只实现读方法或只实现写方法,如只读光盘,那么这样做也是可以的。如果我们知道以后出现的东西都是能读又能写的,那这两个接口就没有必要了。其实如果将只读设备的Write方法留空或抛出异常,也可以不要这两个接口。总之一句话:理论是死的,人是活的,一切从现实需要来,防止设计不足,也要防止设计过度。在这里,我们姑且认为以后的移动存储都是能读又能写的,所以我们选方案三。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - -

23、 - - - 第 7 页,共 24 页 - - - - - - - - - 实现下面,我们要将解决方案加以实现。我选择的语言是C#,但是在代码中不会用到C#特有的性质,所以使用其他语言的朋友一样可以参考。首先编写 IMobileStorage接口:1namespace InterfaceExample 2 3publicinterface IMobileStorage 4 5void Read();/ 从自身读数据6void Write();/ 将数据写入自身7 8比较简单,只有两个方法,没什么好说的,接下来是三个移动存储设备的具体实现代码:U盘 1namespace InterfaceExa

24、mple 2 3publicclass FlashDisk : IMobileStorage 4 5publicvoid Read() 6 7 Console.WriteLine(Reading from FlashDisk,); 8 Console.WriteLine(Read finished!); 9 10名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 24 页 - - - - - - - - - 11publicvoid Write() 12 13 Console

25、.WriteLine(Writing to FlashDisk,); 14 Console.WriteLine(Write finished!); 15 16 17MP3 1namespace InterfaceExample 2 3publicclass MP3Player : IMobileStorage 4 5publicvoid Read() 6 7 Console.WriteLine(Reading from MP3Player,); 8 Console.WriteLine(Read finished!); 9 1011publicvoid Write() 12 13 Console

26、.WriteLine(Writing to MP3Player,); 14 Console.WriteLine(Write finished!); 15 1617publicvoid PlayMusic() 18 19 Console.WriteLine(Music is playing,); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 24 页 - - - - - - - - - 20 21 22移动硬盘 1namespace InterfaceExample 2

27、3publicclass MobileHardDisk : IMobileStorage 4 5publicvoid Read() 6 7 Console.WriteLine(Reading from MobileHardDisk,); 8 Console.WriteLine(Read finished!); 9 1011publicvoid Write() 12 13 Console.WriteLine(Writing to MobileHardDisk,); 14 Console.WriteLine(Write finished!); 15 16 17可以看到,它们都实现了IMobileS

28、torage接口,并重写了各自不同的Read 和 Write 方法。下面,我们来写Computer: 1namespace InterfaceExample 2 3publicclass Computer 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 24 页 - - - - - - - - - 4 5private IMobileStorage _usbDrive; 6 7public IMobileStorage UsbDrive 8 9get10 11retur

29、nthis ._usbDrive; 12 13set14 15this ._usbDrive = value; 16 17 1819public Computer() 20 21 2223public Computer(IMobileStorage usbDrive) 24 25this .UsbDrive = usbDrive; 26 2728publicvoid ReadData() 29 30this ._usbDrive.Read(); 31 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - -

30、- - - 第 11 页,共 24 页 - - - - - - - - - 3233publicvoid WriteData() 34 35this ._usbDrive.Write(); 36 37 38其中的 UsbDrive 就是可替换的移动存储设备,之所以用这个名字,是为了让大家觉得直观,就像我们平常使用电脑上的USB插口插拔设备一样。 OK!下面我们来测试我们的“电脑”和“移动存储设备”是否工作正常。我是用的C#控制台程序,具体代码如下: 1namespace InterfaceExample 2 3class Program 4 5staticvoid Main( string a

31、rgs) 6 7 Computer computer = new Computer(); 8 IMobileStorage mp3Player = new MP3Player(); 9 IMobileStorage flashDisk = new FlashDisk(); 10 IMobileStorage mobileHardDisk = new MobileHardDisk(); 1112 Console.WriteLine(I inserted my MP3 Player into my computer and copy some music to it:); 13 computer.

32、UsbDrive = mp3Player; 14 computer.WriteData(); 15 Console.WriteLine(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 24 页 - - - - - - - - - 1617 Console.WriteLine(Well,I also want to copy a great movie to my computer from a mobile hard disk:); 18 computer.Usb

33、Drive = mobileHardDisk; 19 computer.ReadData(); 20 Console.WriteLine(); 2122 Console.WriteLine(OK!I have to read some files from my flash disk and copy another file to it:); 23 computer.UsbDrive = flashDisk; 24 computer.ReadData(); 25 computer.WriteData(); 26 Console.ReadLine(); 27 28 29现在编译、运行程序,如果

34、没有问题,将看到如下运行结果:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 24 页 - - - - - - - - - 好的,看来我们的系统工作良好。后来,刚过了一个星期,就有人送来了新的移动存储设备NewMobileStorage ,让我测试能不能用,我微微一笑,心想这不是小菜一碟,让我们看看面向接口编程的威力吧!将测试程序修改成如下: 1namespace InterfaceExample 2 3class Program 4 5staticvoid Main(

35、 string args) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 24 页 - - - - - - - - - 6 7 Computer computer = new Computer(); 8 IMobileStorage newMobileStorage = new NewMobileStorage(); 910 Console.WriteLine(Now,I am testing the new mobile storage:); 11 computer

36、.UsbDrive = newMobileStorage; 12 computer.ReadData(); 13 computer.WriteData(); 14 Console.ReadLine(); 15 16 17编译、运行、看结果:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 24 页 - - - - - - - - - 哈哈,神奇吧,Computer 一点都不用改动,就可以使新的设备正常运行。这就是所谓“对扩展开放,对修改关闭”。又过了几天,有人通知我说又有

37、一个叫SuperStorage的移动设备要接到我们的Computer 上,我心想来吧,管你是“超级存储”还是“特级存储”,我的“面向接口编程大法”把你们统统搞定。但是,当设备真的送来,我傻眼了,开发这个新设备的团队没有拿到我们的IMobileStorage 接口,自然也没有遵照这个约定。这个设备的读、写方法不叫Read和 Write ,而是叫 rd 和 wt,这下完了 , 不符合接口啊,插不上。但是,不要着急,我们回到现实来找找解决的办法。我们一起想想:如果你的Computer 上只有 USB接口,而有人拿来一个PS/2 的鼠标要插上用, 你该怎么办?想起来了吧,是不是有一种叫 “PS/2 -

38、USB ”转换器的东西?也叫适配器,可以进行不同接口的转换。对了!程序中也有转换器。这里, 我要引入一个设计模式,叫“Adapter ” 。它的作用就如现实中的适配器一样,把接口不一致的两个插件接合起来。由于本篇不是讲设计模式的,而且Adapter 设计模式很好理解,所以我就不细讲了,先来看我设计的类图吧:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 24 页 - - - - - - - - - 如图所示,虽然SuperStorage没有实现 IMobileStora

39、ge,但我们定义了一个实现IMobileStorage的 SuperStorageAdapter,它聚合了一个SuperStorage ,并将 rd 和 wt 适配为 Read和 Write ,SuperStorageAdapter的具体代码如下: 1namespace InterfaceExample 2 3publicclass SuperStorageAdapter : IMobileStorage 4 5private SuperStorage _superStorage; 6 7public SuperStorage SuperStorage 8 9get10 11returnthi

40、s ._superStorage; 12 13set名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 24 页 - - - - - - - - - 14 15this ._superStorage = value; 16 17 1819publicvoid Read() 20 21this ._superStorage.rd(); 22 2324publicvoid Write() 25 26this ._superStorage.wt(); 27 28 29好,现在我们

41、来测试适配过的新设备,测试代码如下: 1namespace InterfaceExample 2 3class Program 4 5staticvoid Main( string args) 6 7 Computer computer = new Computer(); 8 SuperStorageAdapter superStorageAdapter = new SuperStorageAdapter(); 9 SuperStorage superStorage = new SuperStorage(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - -

42、 - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 24 页 - - - - - - - - - 10 superStorageAdapter.SuperStorage = superStorage; 1112 Console.WriteLine(Now,I am testing the new super storage with adapter:); 13 computer.UsbDrive = superStorageAdapter; 14 computer.ReadData(); 15 computer.WriteData(); 16 Consol

43、e.ReadLine(); 17 18 19运行后会得到如下结果:OK !虽然遇到了一些困难,不过在设计模式的帮助下,我们还是在没有修改Computer 任何代码的情况下实现了新设备的运行。好了,理论在第一篇讲得足够多了,所以这里我就不多讲了。希望各位朋友结合第名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 19 页,共 24 页 - - - - - - - - - 下一篇,我将解析经典设计模式中的面向接口编程思想和.NET 平台分层架构中接口的运用。面向接口编程详解(三)模式研究通

44、过前面两篇,我想各位朋友对“面向接口编程”的思想有了一定认识,并通过第二篇的例子,获得了一定的直观印象。但是,第二篇中的例子旨在展示面向接口编程的实现方法,比较简单,不能体现出面向接口编程的优势和这种思想的内涵。那么,这一篇作为本系列的终结篇,将通过分析几个比较有深度的模式或架构,解析隐藏其背后的面向接口思想。这篇我将要分析的分别是MVC 模式和 .NET平台的分层架构。这篇的内容可能会比较抽象,望谅解。1. 从 MVC 开始MVC 简介:本文不打算详细解释MVC 架构,而是把重点放在其中的面向接口思想上。所以在这里,只对 MVC 做一个简略的介绍。 MVC是一种用于表示层设计的复合设计模式。

45、M 、V、C分别表示模型(Model)、 View(视图)、 Controller(控制器)。它们的职责如下:模型:用于存储应用中的数据及运行逻辑,是应用的实体。视图:负责可视部分,用于与用户交互及呈现数据。视图只负责显示,不负责将用户的操作行为解释给模型。控制器:负责将用户的行为解释给模型。根据指定的策略和用户的操作,调用模型的逻辑。关于三者的关系,我画了一张图,大家请看:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 20 页,共 24 页 - - - - - - - - - 它

46、们之间的交互有以下几种:1. 当用户在视图上做任何需要调用模型的操作时,它的请求将被控制器截获。 2.控制器按照自身指定的策略,将用户行为翻译成模型操作,调用模型相应逻辑实现。 3.控制器可能会在接到视图操作时,指定视图做某些改变。 4.当模型的状态发生改变时,将通过某种方式通知视图。 5.视图可以从模型获取状态,从而改变自己的显示。 MVC介绍完了,那么可能会有人问,我们的主题呢?面向接口思想呢?其实,MVC中处处都存在面向接口的影子。下面,我对其中几个侧面进行解释。 1.首先我们可以看到,视图和模型是有直接交互的,也就是上面的4、5 两点。但是有一点可能会让你吃惊:它们两个谁也不“认识”谁

47、,即它们相互并不知道对方是做什么的、有什么属性、有什么方法,但是它们能交互。这是怎么做到的呢?因为它们个各知道对方实现了某一个接口。此乃面向接口思想一大作用:使相互不认识的类进行交互。这样做是很有好处的,首先它们之间的耦合度大大降低,其次双方都可以进行替换,只要实现了相同的接口,就名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 21 页,共 24 页 - - - - - - - - - 打个不太恰当的比喻。我们都知道120 这个电话号码,是急救电话。其实120 就是个接口,因为当你拨

48、打这个电话时,你不知道那边是哪所医院,甚至不知道那边是不是医院,你只知道电话那头的地方可以救人,也可以说实现了IHelp 接口。这样,你通过一个号码可以说同全部的救人机构联系起来了,当有紧急事件,接线控制那边会将你的请求接到最近可用的机构,你就可以最快的得到帮助。现在我们假设没有使用面向接口思想,来看看会发生什么恐怖的事情:首先,我家的 120 号码是绑定在本市第一人民医院的,即当我拨打120 时,只能拨通第一人民医院。如果有一天我食物中毒了,急忙拨通了120,但是电话那边告诉我他们医院的救护车都派出去了,我问那怎么接通别家医院的电话,那边的MM 很温柔的告诉我,让我打电话给网通公司,然后重新

49、为我布线。于是我吐血而亡,言归正传。这里,我要引入一个设计模式,叫观察着(Observer )模式。这个模式大约是这样的:整个模式中有两种实体:观察者和被观察者,它们分别实现一个接口,这里我们姑且叫做IObserver与 IObserverSubject。IObserver只有一个方法,例如叫Update ,当被观察者状态改变时,调用这个方法,用来通知观察者。IObserverSubject接口有两个方法,都是供观察者调用。一个用来将观察者注册为此被观察者的观察对象,另一个用于将观察者移除。一般情况下,一个被观察者对应多个观察者。在 MVC 中,视图是观察者,模型是被观察者,当模型状态改变时,

50、调用所有观察者的 Update 方法,通知视图模型有变,视图在Update 方法里写下响应代码,完成操作。通过这个方法,视图和模型就可以在仅依赖接口的情形下进行交互,而不必强耦合,而且在模型不变的情况下,视图可以随意替换。(只要实现了IObserver ) 2. 在 MVC 中另一个使用接口的地方就是控制器,这里我要首先引入一个设计模式:策略模式( Strategy)。在 MVC 中,控制器就使用了这个模式。刚才我说过,视图负责与用户交互,但是,它只负责界面显示部分,至于当用户做了某个操作(如单击某个按钮)后系统应该怎么反应,视图并不负责,它只是将这个动作交给控制器,控制器根据内置的策略,将用

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 技术总结

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁