面向接口而非实现进行编程课件.ppt

上传人:scccc 文档编号:11883651 上传时间:2021-10-12 格式:PPT 页数:33 大小:180.50KB
返回 下载 相关 举报
面向接口而非实现进行编程课件.ppt_第1页
第1页 / 共33页
面向接口而非实现进行编程课件.ppt_第2页
第2页 / 共33页
面向接口而非实现进行编程课件.ppt_第3页
第3页 / 共33页
面向接口而非实现进行编程课件.ppt_第4页
第4页 / 共33页
面向接口而非实现进行编程课件.ppt_第5页
第5页 / 共33页
点击查看更多>>
资源描述

《面向接口而非实现进行编程课件.ppt》由会员分享,可在线阅读,更多相关《面向接口而非实现进行编程课件.ppt(33页珍藏版)》请在三一文库上搜索。

1、面向接口而非实现进行编程,1,第六章 面向接口而非实现进行编程,6,第六 章,面向接口而非实现进行编程,2,API 是文档的说明和接口的说明总称。通常类的组成是包括公开和非公开的成员两部分。 上一章说到:API公开的内容越少越好。 将代码分成接口和实现两部分,在编写代码时,让系统的其它部分只依赖于接口这是我们呈现设计的习惯。 接口是用来公开给使用只的说明部分,实现是类内部的具体实现过程。,面向接口而非实现进行编程,3,方法添加容易与移去难 设计者带来的问题往往远远多于其解决的问题。向API中添加一个新方法是很容易的一件事,但与此相反,想从API中移徐一个方法却非常困难。一个API对外提供的功能

2、越多,那么为保持向后兼容性所做的工作也就越多。提供的功能越多留给具体实现的空间也就越少。如果API公开的不必要的内容越多,可改进的空间也就越少。,方法的添加与移去,面向接口而非实现进行编程,4,1 代码不是API: 需要经过抽象的说明才是API,没有经过重构,那么公开的很可能不是API,而是内部的具体实现。千万不要把代码当成API,还要花精力来整理。 2 公布的是接口不是实现:给调用者是接口应用,不是公布类的具体实现描述。 3 逻辑分离与物理分离: 只是把类说明,和类实现分离,但文件还是在以前。 4 物理分离: 接口说明和实现说明分别在两个不同的文件中,达到物理的分离。,公布的是接口不是实现,

3、面向接口而非实现进行编程,5,编程应该面向接口而非现实:在使用API时,应该遵守正确的原则。 不要依赖没说明的属性和文件资源:不要去依赖那些没有在文档中提起的属性和文件资源。 提出合适API 要求:正确的做事方法是向设计者要求提出合适API。那种自用示公开内容来完成某种功能的做法是非常脆弱的,会因为版本、环境的不同而无法正常运行。,编程应该面向接口而非现实,面向接口而非实现进行编程,6,正确理解面向接口编程的概念,Iterface只是接口说明:能够清楚地理解面向接口编程并不是对应着Java中的Iterface,这种编程方式只是将其抽象定义与实际的实现这两类内容进行分离。 类的使用特点:何时使用

4、类 接口使用特点:何时使用接口,面向接口而非实现进行编程,7,6.1 移除方法或者字段,不要随意移去方法和属性: (1)设计方法或属性在使用: (2)类会对相关的方法和属性设置访问权限。(3)类的成员被继承:,面向接口而非实现进行编程,8,设计方法或属性在使用,从已经公开的类或者接口中移除方法或者字段是一件错误的事情。系统公开,可能说明给方法或属性具有一定使用代表性,这样就会有其他成员在使用。 一个方法或者字段被定义为private或者是默认的package访问级别,那么对于外部代码来说,它是不可见的,也就无法进行访问。这种情况,从类中移除该内容,不会引起什么问题,但没什么意义。,面向接口而非

5、实现进行编程,9,类对相关方法和属性设置访问权限,类的设计者肯定会对类的成员根据实际使用需要设置成:PUBLIC,PROTECTED,PRIVATE等,如果你移去,就会造成该给访问的没办法访问,不能访问的有多此一举。,面向接口而非实现进行编程,10,移去方法,对于源代码和二进制来讲,移除一个抽象的proteced方法是可以兼容的。从功能角度来说,可能是并不兼容。那个方法当时被动放到类中,应该是有本应 的目的,而子类也可能是会重载该是方法,并希望在合适的时候被动调用 。他们的实现就不能被调用了,theMethod方法语义也发生了改变,则子类是无法重载这个方法的。,面向接口而非实现进行编程,11,

6、6.2 移除或者添加一个类或者接口,如果一个类或者接口可以被外部访问,就意味着其方法可能会被调用,或者其字段可能被引用,一旦类和接口成为API,两者就没什么区别了,都必须长久地存在下去。 类和接口其实是没有很大区别,类强调封装性,接口强调调用方法或引用方法。,面向接口而非实现进行编程,12,6.3 向现有的继承体系中添加接口或者类,向现有的继承体系中添加类或者接口可以带来很多好处: (1)简化API: 不必要公开那么多 (2) 引同更统一 (3)维护更方便,面向接口而非实现进行编程,13,例子说明,Public abstract String sayHello(); Public abstra

7、ct String sayHelloto(String wgo); 作者希望可以简化这个API Public abstract class SimpleHelloClass Public abstract String sayHello(); 当然,以前编写的类仍然需要维护。 Public abstract class helloClass extends SimpleHelloClass 简单 只需要维护这里就可以,面向接口而非实现进行编程,14,工厂方法支持参数化的返回类型(2),Public final class Template extends object Private fina

8、l Class type; Public Template(Class type this.type=type; Public Class getType() return type; /now what!? Public Template()this(object.class); ,面向接口而非实现进行编程,15,工厂方法支持参数化的返回类型(3),Public final class Template extends object Private final Class type; Public Template(Class type this.type=type; Public Clas

9、s getType() return type; Deprecated SuppressWarnings(“unchecked”) Public Template()this(Class)object.class); Public static Template create() Return new Template(object.class) ,面向接口而非实现进行编程,16,5.3 让所有的内容都不可更改,不考虑让其拥有子类,这个类不能被继承。否则API一旦发布以后,会有各种使用方式,大量无法预计的事情。 Public class Hello Public void hello() Sy

10、stem.out.println (“Hello”); 直接公开这个可被继承的Hello类,会有很多代码,是直接从外部调用Hello的Hello方法的: Public static void sayHello () Hello Hello=new Hello(); Hello.Hello(); ,面向接口而非实现进行编程,17,各种使用方式,开发人员也可编写一个继承Hello的类MyHello,重载hello方法,代码如下。 Private static class MyHello extends Hello Override Public void hello() System.out.pr

11、intln(“Hi”); Private static class SuperHello extends Hello Override Public void hello() Super.hello(); System.out.println(“Hello once again”); ,面向接口而非实现进行编程,18,6.4 添加方法或者字段(1),(1) 尽量少用字段:应该避免在允许继承的类或者接口中添加新的抽象方法。如果是类,请确保该类不可被继承。 (2)添加一个抽象方法可能不向后兼容:向类中添加一个抽象方法,则会强迫其非抽象的子类来实现该是抽象方法,这种改变是做不到向后兼容的。这种处理对

12、于源代码来说是不兼容的。,面向接口而非实现进行编程,19,6.4 添加方法或者字段(2),(3)避免继承类添加新抽象方法: 在对API进行改进时,与方法相比,字段受到的约束更多。这正是要避免在API中使用字段的原因;当然那种使用static和final声明的常用字段是可以添加到API中的。 (4)不要在接口中添加一个非抽象方法:能添加抽象方法的只能是类,不可能在接口中添加一个非抽象方法。无论是向一个类还是一个接口中添加一个方法,只要这两者可以被继承,那么这种改变就做不到了百分百兼容。,面向接口而非实现进行编程,20,6.5 Java中接口和类的区别,多继承:Java接口最突出的特性就是多继承。

13、因为多继承可以减少对内存的占用。利用多继承公使用一个对象,就可以实现API中公开的多个接口。 类继承:类继承则只能有一个父类,此时如果类之间有些数据需要互访或者调用方法,那么只能用委托的方式。这样会占用很多空间,如果只是一两个,就不是那么明显了。性能方面的考虑就不是主要因素了。,面向接口而非实现进行编程,21,6.6 弱点背后的优点(1),向现有接口中添加方法总不太容易。要向后兼容的话,那么添加方法就不是有多困难的问题,而是几乎不可能完成的任务。 (1) 方法维护麻烦 (2) 引用麻烦 (3) 版本保持向后兼容麻烦 那么就利用不祝来改变设计方法: 采用多版本命名接口,保持系统兼容。 对于语言的

14、不同版本,要决定分别支持哪些功能。接口是一个非常合适的工具,面向接口而非实现进行编程,22,6.6 弱点背后的优点(2),Public interface InstanceProvide Public Class instanceClass() throws exception; Public Object instanceCreate() throws Exception ; 把常用的专用到一个类中,提高整体运行效率。 创建了如下这个接口: Public interface BetterInstanceProvider extends InstanceProvider Public Bool

15、ean isInstanceof(Class c); ,面向接口而非实现进行编程,23,6.6 弱点背后的优点(3),If (instance instanceof BetterInstanceProvider) betterInstanceProvider bip= (BetterInsatnceProvider)instance; return bip.isInstanceof(string.class); else Return string.class.isAssignableFrom(instance.instanceClass(); ,面向接口而非实现进行编程,24,6.7 添加方

16、法的另一种方案(1),禁止类被继承:利用 final:把一个类声明为final,就表示这个类是不可被继承的。因此那种在接口或者抽象类中添加方法而引起的问题,对于这个final类来说就不会出现了。由于在类的二进制文件中,对于要调用的方法,是可以通过名称、参数及返回值来唯一确定的,所以不会产生兼容性的问题。 不要定义具有相同数量参数同名方法:像theObject.add(null)这句代码,编译器就会给出一个编译错误,这这句代码中要方法具有二义性。要避免的方法很简单,就是不要加入具有相同数量的参数的同名方法。,面向接口而非实现进行编程,25,6.7 添加方法的另一种方案(2),Import jav

17、a.util.concurrent.Callable; Public final class InstanceProvider Private final Callable instance; Public InstanceProvider(Callable instance) This.instance=instance; Public Class instanceClass() throws Exception Return instance.call().getClass(); Public Object instanceCreate() throws Exception Return

18、instance.call(); ,面向接口而非实现进行编程,26,6.7 添加方法的另一种方案(3),Public abstract class Accessor Private static volatile Accessor DEFAULT; Public static Accessor getDefauIt() Accessor a=DEFAULT; If (a!=null) Return a; Try Class.forName(Item.class.getName(),Item,Item.class.getClassLoader(); catch (Exception ex) Ex

19、.printStackTrace(); Return DEFAULT; Return DEFAULT;,面向接口而非实现进行编程,27,6.8 抽象类有没有用呢,在一个API中,抽象类其实一直备受质疑,如果API中使用了抽象类,通常就会被动认为这是因为设计者没有投入足够的时间来合理地设计API。 相对于Java接口,Java抽象类还有一些其他方面的优势,那就是抽象类可以包含static方法。,面向接口而非实现进行编程,28,抽象类有没有用呢(2),Public abstract class InterfaceThatJustJoeCanImplement Protected Interface

20、ThatJustJoeCanImplement () If (!”impl.joe.joesImpl”.equals(getClass().getName() Throw new IllegalStateException(“Sorry you are not allowed to implement this class”); Public abstract void everyoneCallThisJoeWillHandleTheRequest();,面向接口而非实现进行编程,29,6.9 要为增加参数做好准备(1),对API进行修改,那么最常见的问题就是如何通过添加方法的参数来增强现有方

21、法的功能。 Public abstract class compute Public abstract List getData(); Public Map getDataAndDescription() LinkedHashMap ret=new LinkedHashMap(); For (String s :getData() Ret.put(s,s); Return ret; ,面向接口而非实现进行编程,30,6.9 要为增加参数做好准备(2),对于客户来说,给他一个类去实现,就不如给他一个接口来实现,后者看起来更像是一种解决方案。同时在一个可以子类化的类中添加一个方法总是有些危险的。

22、Public interface Compute Public void computeData(Requst request,Response response); Public final class Request ,面向接口而非实现进行编程,31,6.9 要为增加参数做好准备(3),Public final class Response Private final Map result) ; Response(Map result) This.result=result; Public void add(String s) Result.put(s,s); Public void ad

23、dAll(List all) For (String s:all) Add(s); Public void add(String s,String description) Result.put(s,description); ,面向接口而非实现进行编程,32,6.9 要为增加参数做好准备(3),只需要向Compute.Request类添加新的获取方法,就可以为computeData方法添加新的参数,同时因为Compute.Request这个类声明为final,所以它的方法只能被动调用,不可能被重载。这就意味着向该是类中添加方法是非常安全的。 这个方法有太多的数据需要返回,也可以用向Response类中添加新的设置方法。 采取这种模式,一定要把Requst和Response类都是声明为final类,如果不将他们声明为接口的话,在对这个系统进行改进时,就会平添很多麻烦。,面向接口而非实现进行编程,33,6.10 接口VS类,总而言之,编程时应该面向接口而非面向现实。所谓的接口并不是指Java中的Inteface,而是指抽象内容,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1