Java编程思想第四版第九章学习——接口
2016-05-27 15:25
357 查看
1、抽象类
包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的。创建抽象类和抽象方法的好处是可以使类的抽象性明确起来,并告诉用户和编译器打算如何来使用它们。抽象类还是很有用的重构工具,因为它们使得我们可以很容易地将公共方法沿着继承层次结构向上移动。如果从一个抽象类继承,并想创建该新类的对象,就必须为基类中的所有抽象方法提供方法定义,如果不这么做,那么导出类也是抽象类,且编译器将会强制用abstract这个关键字来限定这个类。
2、接口
interface这个关键字产生一个完全抽象的类,它不提供任何具体实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。接口只提供了形式。要想创建一个接口,需要用interface关键字来替代class关键字。前面可加public等访问权限关键字。接口可以包含域,但是这些域隐式地是static和final的。要让一个类遵循某个特定接口(或者是一组接口),需要使用implements关键字,表示的是interface只是它的外貌,现在要声明它是如何工作的。
3、完全解耦
策略设计模式:创建一个能够根据所传递的参数对象的不同而具有不同行为的方法,被称为策略设计模式。这里方法包含所要执行的算法中固定不变的部分,而“策略”包含变化的部分。策略就是传递进去的参数对象,它包含要执行的代码。(关于策略模式的说明,在网上看了一些,介绍的很详细。我找了一篇通俗易懂的,http://yangguangfu.iteye.com/blog/815107,大家如果还有什么问题,欢迎探讨)
不过在我看了策略模式后,我想到了之前向上转型时用到的工厂模式,感觉它们比较相似,为了区别,特别学习了一下。和大家分享。
策略模式和工厂模式的区别:
(1)关注点不同
策略模式关注行为的封装,而工厂模式关注对象创建。
(2)用途不同
策略模式是行为型模式,它的作用是让一个对象在许多行为中选择一个行为。
工厂模式是创建型模式,它的作用是创建对象
(3)解决的问题不同
策略模式是为了解决策略的切换和拓展,即定义策略族,分别封装起来,使它们之间可以相互替代。策略模式实现了策略的变化独立于使用策略的客户。
工厂模式接受指令,创建出符合要求的实例。它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用对象无关。主要用于多数据库选择、类库文件加载等。
工厂相当于黑盒子,而策略相当于白盒子。
适配器设计模式:适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
4、多重继承
在导出类中,不强制要求必须有一个是抽象的或“具体的”(没有任何抽象方法的)基类。如果要从一个非接口的类继承,那么只能从一个类去继承。其余的基元素都必须是接口。需要将所有的接口名都置于implements关键字之后,用逗号将它们一一隔开。可以继承任意多个接口,并可以向上转型为每个接口,因为每一个接口都是一个独立类型。(当通过这种方式把一个具体类和多个接口组合到一起时,这个具体类必须放在前面,后面跟着的才是接口)下面举个书上的例子:interface CanFight{void fight();} interface CanSwim{void swim();} interface CanFly{void fly();} class ActionCharacter{ public void fight(){} } class Hero extends ActionCharacter implements CanFight,CanSwim,CanFly { public void swim() {} public void fly() {} } public class Adventure { public static void t(CanFight x) {x.fight();} public static void u(CanSwim x) {x.swim();} public static void v(CanFly x) {x.fly();} public static void w(ActionCharacter x) {x.fight();} public static void main(String[] args){ Hero h =new Hero(); t(h); //Treat it as a CanFight u(h); //Treat it as a CanSwim v(h); //Treat it as a CanFly w(h); //Treat it as an ActionCharacter } }
使用接口的核心原因:
(1)能够向上转型为多个基类型(以及由此而带来的灵活性)。
(2)防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。(这和使用抽象基类目的相同)
注意:如果知道某事物应该成为一个基类,第一选择是使它成为一个接口。
通过继承,可以在接口中添加新的方法声明,还可以通过继承在新接口中组合数个接口。
如下图所示
在Vampire中使用的语法仅适用于接口继承。一般情况下,只可以将extends用于单一类,但可以引用多个基类接口。
Notice:组合接口时可能会出现名字冲突,在打算组合的不同接口中使用相同的方法名通常会造成代码可读性的混乱,尽量避免。
5、接口中的域
(1)接口中的域都自动是static和final的,所以接口可以便捷的用来创建常量组。(2)接口中的定义的域不能使“空final”,但可以是被非常量表达式初始化的。如下所示:
Random RAND = new Random(47); int RANDOM_INT = RAND.nextInt(10); long RANDOM_LONG = RAND.nextLong() * 10; float RANDOM_FLOAT = RAND.nextLong() * 10; double RANDOM_DOUBLE = RAND.nextDouble() * 10;
同时,因为域是static的,它们可以在类第一次被加载时被初始化,发生在任何域首次被访问时。
6、嵌套接口
在Java语言中,接口可以嵌套在类或其它接口中。由于Java中interface内是不可以嵌套class的,所以接口的嵌套就共有两种方式:class嵌套interface、interface嵌套interface。class嵌套interface
这时接口可以是public,private和package的。重点在private上,被定义为私有的接口只能在接口所在的类被实现。可以被实现为public的类也可以被实现为private。需要注意的是,当被实现为public时,只能在被自身所在的类内部使用。只能够实现接口中的方法,它可以强制该接口中的方法定义不要添加任何类型信息(也就是说,不允许向上转型),例如:
class A { private interface D{ void f();} private class DImp implements D{ public void f() {} } public class DImp2 implements D { public void f() {}} public D getD() {return new DImp2();} private D dRef; public void receiveD(D d) { dRef = d; dRef.f(); } } public class NestingInterfaces { public static void main (String[] args) { A a = new A(); //The type A.D is not visible //! A.D ad = a.getD(); //Cannot convert from A.D to A.DImp2 //! A.DImp2 di2 = a.getD(); //The type A.D is not visible //! a.getD().f(); A a2 = new A(); a2.receiveD(a.getD()); }
如上,A.DImp2只能被自身所使用。
下面看看getD()方法,它是一个返回对private接口的引用的public方法。此时,可以看出数次尝试使用返回值都失败了,只有一个方式可以成功,就是将返回值交给有权使用它的对象。
interface嵌套interface
由于接口的元素必须是public的,所以被嵌套的接口自动就是public的,而不能定义成private的。在实现这种嵌套时,不必实现被嵌套的接口。
interface E { interface G {void f();} public interface H { void f();} void g(); }
不要滥用结合和工厂
创建类,基本上可以替代为一个接口和一个工厂。如果一言不合就去创建接口和工厂,这样看起来好像是需要使用不同的具体实现,因此总是添加这样的抽象性。但事实是抽象性应该是应真正的需求而产生的。当必须的时候,重构接口而不是添加额外级别的间接性,增加额外的复杂性。
恰当的原则是优先选择类而不是接口。从类开始,如果接口的必须性非常明确,就进行重构。接口是一种工具,但不要滥用。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树