3.1、抽象类与接口()
抽象类更多的情况下是作为一个模板使用,而接口更多的情况下是作为一个标准出现。
3.1.1、适配器设计
一个子类如果实现了一个接口,则肯定要覆写接口中的全部方法,那是否有一种方式,可以让子类有选择的去实现接口中的方法,而不是全都实现呢?
interface A{
public void printA() ;
public void printB() ;
public void printC() ;
public void printD() ;
public void printE() ;
}
|
以上的接口的子类能否有选择性的进行所需要方法的覆写呢?
interface A{
public void printA() ;
public void printB() ;
public void printC() ;
public void printD() ;
public void printE() ;
}
abstract class AAdapter implements A{
//
方法全部实现
//
但是此类是中间过渡类,不能直接使用,所以此时应该把此类定义成抽象类。
public void printA() {}
public void printB() {}
public void printC() {}
public void printD() {}
public void printE() {}
};
class AAA extends AA{
public void printA() {
System.out.println("dafa");
}
};
|
思考:
张三去酒会参加活动,碰见了一个美国女孩,想跟她说“HELLO,MAKE FRIEND”,第二次又参加了一个舞会,又碰见了一个中国的女孩,想跟她说“你好,我想跟你交朋友”。
· 碰见美国人说英语
· 碰见中国人说中文
· 接口的第二个作用就是表示一种能力。
interface SayChina{
public void sayChina() ;
}
interface SayEnglish{
public void sayEnglish() ;
}
class Person implements SayChina,SayEnglish{
public void sayChina(){
System.out.println("
你好,交朋友吧!
") ;
}
public void sayEnglish(){
System.out.println("HELLO,MAKE FRIEND!") ;
}
};
|
3.1.2、代理设计
思考:
现在孙键欠了我500000000元钱,此时,王宁是一个老实人,孙键欺负他,不还,之后王宁没有办法了,找到了王伟(专门的讨债公司),准备好了绳索、刀子、枪支,从孙键手里把银子要了回来,之后销毁了一切的证据。但是王宁只管拿回了自己的钱。
可以按照以下的形式组织代码:
interface Subject{
public void giveMoney() ;
}
class RealSubject implements Subject{
public void giveMoney(){
System.out.println("
把钱拿回。。。
") ;
}
};
class ProxySubject implements Subject{
private Subject sub = null ;
public ProxySubject(Subject sub){
this.sub = sub ;
}
public void before(){
System.out.println("
要准备绳索、刀子、枪支。。。
") ;
}
public void giveMoney(){
this.before() ;
this.sub.giveMoney() ;
this.after() ;
}
public void after(){
System.out.println("
销毁一切的罪证。。。
") ;
}
};
public class Demo06{
public static void main(String args[]){
Subject sub = new ProxySubject(new RealSubject()) ;
sub.giveMoney() ;
}
};
|
3.1.3、工厂设计
问题的引出:现在使用一个接口,同时定义出子类,通过子类为接口进行实例化:
interface Fruit{
public void eat() ;
}
class Apple implements Fruit{
public void eat(){
System.out.println("
吃苹果。。。
") ;
}
};
public class Demo07{
public static void main(String args[]){
Fruit f = new Apple() ;
f.eat() ;
}
};
|
以上代码存在问题?
· main方法实际上相当于是一个客户端程序
· 如果现在需要换一个子类了,那么就要修改客户端。
· 好的程序:某一处的更改不影响调用处
造成以上问题的根源:
· 子类直接在客户端使用,耦合度太深了。
在对象实例化的中间加入一个过渡端,所谓的解耦合最大的特点就是永远有一个过渡端。
那么现在加入一个过渡端:
interface Fruit{
public void eat() ;
}
class Apple implements Fruit{
public void eat(){
System.out.println("
吃苹果。。。
") ;
}
};
class Cherry implements Fruit{
public void eat(){
System.out.println("
吃樱桃。。。
") ;
}
};
class Factory{
public static Fruit getInstance(String str){
Fruit f = null ;
if("apple".equals(str)){
f = new Apple() ;
}
if("cherry".equals(str)){
f = new Cherry() ;
}
return f ;
}
};
public class Demo08{
public static void main(String args[]){
Fruit f = Factory.getInstance(args[0]) ;
if(f!=null)
f.eat() ;
}
};
|
此时,发现程序的客户端没有任何的改变,而直接可以选择各种所要的子类。那么通过工厂取得全部的接口实例,那么以后修改的时候就可以只修改工厂了。
3.1.4、抽象类与接口的区别()
区别点
|
抽象类
|
接口
|
定义
|
abstract class
抽象类名称
{}
|
interface
接口名称
{}
|
概念
|
包含一个抽象方法的类就是抽象类,除此之外还包含常量、变量、普通方法、构造方法
|
只包含全局常量和抽象方法的类称为接口
|
使用
|
需要通过子类继承
class
子类
extends
父类
|
需要通过子类实现
class
子类
implements
接口
|
关系
|
一个抽象类可以实现多个接口,一个接口不能继承一个抽象类
|
|
作用
|
提供了一个模板
|
提供了一个标准,或者说表示了一种能力
|
设计模式
|
模板设计模式
|
工厂设计模式、代理设计模式
|
适配器设计模式
|
||
限制
|
抽象类有单继承局限
|
无此局限
|
应用
|
如果抽象类与接口同时都可以使用,优先使用接口
|
|
特殊点
|
一个抽象类可以包含一个接口或一个抽象类
|
一个接口中也可以包含抽象类或接口
|
特殊点:
1、 一个抽象类中能否包含一个接口?可以
abstract class A{
public abstract void printA() ;
interface B{
public void printB() ;
}
};
class DA extends A{
public void printA(){}
class DB implements B{
public void printB(){}
};
};
|
2、 一个接口中能否包含一个抽象类?可以
interface A{
public abstract void printA() ;
abstract class B{
public abstract void printB() ;
}
};
class DA implements A{
public void printA(){}
class DB extends B{
public void printB(){}
};
};
|
观察以下的题目,写出输出结果:
abstract class A{
public A(){
this.print() ;
}
public abstract void print() ;
}
class B extends A{
private int i = 10 ;
public B(int i){
this.i = i ;
}
public void print(){
System.out.println(this.i) ;
}
};
public class Demo11{
public static void main(String artgs[]){
new B(100) ;
}
};
|
答案是0
子类对象实例化之前,肯定要先去调用父类中的无参构造方法,为父类中的属性初始化,但是父类中的方法未调用完之前,子类的内容并没有初始化,如果没有初始化,则会安排默认值,默认值就是“0”。
本文转自 李兴华 51CTO博客,原文链接:http://blog.51cto.com/lixinghua/96923,如需转载请自行联系原作者