作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/
a)使用场景:解决多重继承和Client需要多Service_Provider的支持。
b)典型UML:
c)举例:薪水计算类的设计
不同的类别有不同的薪水计算方法,那么getSalary方法可以抽象到一个接口SalaryCalculator内,这样在Client进行调用时就会有多态的效果:
public interface SalaryCalculator {
public double getSalary();
}
public class Employee {
SalaryCalculator empType;
String name;
public Employee(String s, SalaryCalculator c) {
name = s;
empType = c;
}
public void display() {
System.out.println("Name=" + name);
System.out.println("salary= " + empType.getSalary());
}
}
public class CategoryA implements SalaryCalculator {
double baseSalary;
double OT;
public CategoryA(double base, double overTime) {
baseSalary = base;
OT = overTime;
}
public double getSalary() {
return (baseSalary + OT);
}
}
public class CategoryB implements SalaryCalculator {
double salesAmt;
double baseSalary;
final static double commission = 0.02;
public CategoryB(double sa, double base) {
baseSalary = base;
salesAmt = sa;
}
public double getSalary() {
return (baseSalary + (commission * salesAmt));
}
}
public class MainApp {
public static void main(String [] args) {
SalaryCalculator c = new CategoryA(10000, 200);
Employee e = new Employee ("Jennifer”,c);
e.display();
c = new CategoryB(20000, 800);
e = new Employee ("Shania”,c);
e.display();
}
}
补充问题:
1.为什么不支持多重继承:依据Sun的官方说法是,避免c++那样管理多重继承的层次关系而带来的复杂性(主要是在多态覆盖方法的时候采用的动态绑定机制),换成用接口来实现多重继承的大部分功能,一个类只能有一个父类,但可以有多个接口,以此对多继承提供了有力的支持。
2.类中声明了系统可以提供的服务,类似于电路中的模块,但是不包含具体的实现。要表达“这是我要完成的任务,除此之外的细节不归我操心”时就用接口,例如:
public interface Photographable{
public void takePhoto();
}
3.接口中的成员变量默认都是public、static、final类型,因此必须被显示初始化。方法默认都是public、abstract。这是必须遵守的。
4.接口没有构造方法,不能被实例化。与抽象类不同,接口不能提供任何具体实现。
5.一个接口不能实现另一个接口,但是它可以继承多个接口。例如:
public interface C extends A,B{
void methodC();
}
6.接口必须通过类来实现它的抽象方法,例如:
public class Glass implements Transparency{...}
要是一个类要实现某个接口时,它必须实现接口中所有的抽象方法,除非这个类被定义为抽象类。若想要修改一个interface但影响太大又不能修改,则可以声明一个新的interface来继承原来的interface,并在其中增加操作。然后在使用的时候还面向父接口的同时,加上instanceof去判断,然后进行强制类型转换——这是个蹩脚的设计,来对待蹩脚的问题。
7.允许定义接口类型的引用变量去引用实现了该接口的类的实例:
Transparency t=new Glass();
8.抽象类vs接口:这个问题最终归结于接口会不会变化、实现类是不是需要同时支持多个接口。抽象类与接口都是位于继承树的上方,都不能被实例化,都可以包含抽象方法。但前者可以提供默认实现,而后者则必须包含抽象方法。接口一旦确定就不能随意改动了,否则就带来太大的麻烦,所以接口一般被用来作为纯粹的规格描述。接口不要求它的实现类在语义上是同一种类型,所以要是非同类型的相同方法类型则使用接口,利于继承树的合理化。接口是系统最高层次的抽象类型。而抽象类则是介于“抽象”和“实现”之间的半成品,抽象类力所能及地完成了部分实现。定制模式就是一种接口颗粒度细化的设计模式。抽象类是为了逻辑的封装,包含部分实现,同时要求子类必须按照某种方式实现。
抽象类为类型建模,接口类为能力建模,同样都是is-a关系,前者表示类型上的,后者表示具备能力上的。
9.针对接口设计的实质:接口用稳定性封装了易变化的部分,在实际的设计中,将稳定部分抽象为接口,然后将不稳定的具体实现设定为实现该接口的类,在方法中利用接口将变化封装起来作为传入参数,调用其中接口定义的方法即可,这个方法根本不知道具体的实现,只是作为封装变化的一个中转站。调用的时候直接传入一个想使用的具体实现类。
10)注意:一个类继承了一个父类,并且实现了多个接口,extends放在implement前边.