本帖最后由 321哈哈哈 于 2017-10-12 02:22 编辑
接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法?? 抽象类(抽象基类)是一种重要而必须的工具,因为你不可能总是使用纯接口?? 希望通过这个通用接口操纵一系列类。 创建抽象类对象没有意义(是用来被继承的)。为了阻止使用者这样做,java提供了抽象方法机制(仅有声明,用abstract,没有方法体,具体实现交给该类的子类)。 含有抽象方法的类必须被声明为抽象的(abstract),抽象类可能不含有抽象方法。 编译器会阻止我们创建抽象类对象。 抽象类的导出类必须为基类所有抽象方法提供方法定义(实现),否则也要声明为抽象的。 抽象类和抽象方法使类的抽象性明确起来,并告诉用户和编译器打算怎样来使用它们。 抽象类还是很有用的重构工具(使我们很容易得将公共方法沿着继承层次结构向上移动)。 重构:从一组类中抽取抽象基类(只抽取了方法声明,因为不同类中的方法实现不同) 抽象类可能代表现实中抽象概念(比如“犬科”) 接口(一个完全抽象的类) 表示:“所有实现了该特定接口的类看起来都像这样” 被用来建立类与类之间的协议 实现(伪)多重继承(同时实现多个接口),使一个类型能向上转型为多种基类类型。(向上转型的结果可以是普通类、抽象类、接口) 可用public(与文件名相同)或者default(不写)来修饰接口 接口包含的域(字段)都是static和final的(不能是空final;可以用非常量表达式初始化) 包含的方法都是public和abstract的(没有方法体) Implements(实现)关键字表示:“interface只是它的外貌,但是现在我要声明它是如何工作的” 实现一个接口时,接口的方法实现都必须被定义为public的 多态是程序语言对规律的表达 但如果这样表达:“如果它是XX,它就能XXX”(用继承),则是对规律的束缚,因为规律太依赖特定条件(必须继承某父类),耦合过紧,灵活性降低,代码复用性较差 应这样表达:“如果它具有特征XX,它就能XXX”(特征用接口表达),规律的应用就更灵活,不再依赖特定的继承体系 复用代码的第一种方式是遵循该接口来编写他们的类(将共同元素抽取为显式“特征”,即接口,然后利用多态)(将接口从具体实现中解耦) 如果无法修改想使用的类(完全可以当做该接口的实现类,但我们无法修改),可以使用适配器模式,然后将适配器类的对象传给当做接口对象来用 被复用是接受接口对象的方法 适配接口 接口吸引人的原因之一是允许同一个接口具有多个不同的具体实现(实现接口前它可能是任何类,只要实现接口之后给出方法的实现就行) 指定方法可以接收的接口类型,每个对象都能适配之后使用该方法(实现该接口),使方法灵活通用可复用(常见用法:策略设计模式) 通过继承(extends)来扩展接口 新接口可以继承多个接口,并可以添加新方法 继承类(可能同时实现多个接口)时的名字冲突 如果构成重载,那就在子类(实现类)中重载 如果方法完全相同(包括返回值):都来自接口的话就留一个;或者把父类方法当做接口方法的实现 只有返回值不同会报错:两个接口不兼容;或者将父类方法当做接口方法的实现失败 在打算组合的各个接口中最好不要使用相同的方法名(避免代码可读性的混乱) 嵌套接口(接口在类或者接口中定义)(生僻特性) 类中可以定义default、public和private的接口 接口中的所有元素默认为public的(包括其中嵌套的接口) 类中的private接口只在本类中可见;外界也获取不到实现该接口的类的对象 外界用 外部类.内部接口(外部接口.内部接口) 这格式使用可见的嵌套接口 实现某个接口时,并不需要实现其中嵌套的接口 含内部接口的类可以创建对象(本身不是抽象类的话) Tip:p175 策略设计模式:创建一个能够根据所传递的参数对象的不同而具有不同行为的方法 方法包含所要执行的算法中固定不变的部分 “策略”(就是传进去的参数对象,都是方法指定接收的接口对象)包含变化的部分(虽然实现了同一个接口,但有不同实现) 适配器模式:p177 前提:想利用的类(Xxx)无法修改,但需要的是实现了特定接口的类(某方法可能只接收该接口对象)。且Xxx类看上去就像实现了该接口一样(其实没有) 方法:写一个适配器类(XxxAdapter),实现了所需接口。包含一个Xxx类成员对象。类中接口的方法实现用Xxx对象来完成(Xxx类本身就有一个方法像是接口方法的实现)(代理) 工厂方法设计模式:p187 生成遵循某个接口的对象的典型方式 我们在工厂对象上调用创建方法,生成接口的某个实现类的对象(不同的工厂生产不同的实现类对象) 与直接调用构造器不同,这种方式使我们的代码完全与接口的实现分离(接口的实现被封装在了工厂的创建方法中?)?? 为什么要添加这种额外级别的间接性呢,常见的原因是想要创建框架(在相同的棋盘上下国际象棋和西洋跳棋)(复用框架?测试类含有接收工厂接口的方法,就是框架?)?? 更加优雅的工厂实现方式(匿名内部类) import static net.mindview.util.Print.*; interface Service { void method1(); void method2(); } interface ServiceFactory { Service getService(); } class Implementation1 implements Service { Implementation1() {} // Package access public void method1() {print("Implementation1 method1");} public void method2() {print("Implementation1 method2");} } class Implementation1Factory implements ServiceFactory { public Service getService() { return new Implementation1(); } } class Implementation2 implements Service { Implementation2() {} // Package access public void method1() {print("Implementation2 method1");} public void method2() {print("Implementation2 method2");} } class Implementation2Factory implements ServiceFactory { public Service getService() { return new Implementation2(); } } public class Factories { public static void serviceConsumer(ServiceFactory fact) { Service s = fact.getService(); s.method1(); s.method2(); } public static void main(String[] args) { serviceConsumer(new Implementation1Factory()); // Implementations are completely interchangeable: serviceConsumer(new Implementation2Factory()); } } /* Output: Implementation1 method1 Implementation1 method2 Implementation2 method1 Implementation2 method2 *///:~ 工厂设计模式可能的误用: 创建接口和对应的工厂貌似就能代替创建一个类了??(都能产生一个类的对象),还抽出了接口(抽象性)备用,需要其他具体实现类的时候可用。但这是一种草率的优化设计。 任何抽象性都是应真正的需求而产生的(需要向上转型了)。当必须时,应该重构接口,而不是到处添加额外级别的间接性,由此带来额外的复杂性。 恰当的原则是:优先选择类而不是接口,如果接口的必须性变得非常明确,就进行重构 抽象类中也可以有main方法 因为接口中的域都自动是static和final的,接口就成了一种很便捷的创建常量组的工具。后被enum代替了。 return ++events != EVENTS; return语句中完成了events的自增 while (t.event()) ; while循环的这种用法:event()返回值为boolean(相当于循环控制条件表达式),而且这个方法会访问对象成员(相当于初始化表达式),方法中包含了原本要在while语句块中执行的语句体和循环后操作语句(比如上例中的返回语句) |