1.接口的基本定义
尽量详细,日后翻阅方便,干货。
1)基础概念
如果一个类之后只有由抽象方法和全局常量组成的,那么在这种情况下不会将其定义为一个抽象类,而只会将其定义为接口,所谓接口严格来说就属于一个特殊的类,而且这个类里面,只有抽象方法和全局常量,连构造方法都没有。
interface A { //定义了接口
public static final String MSG = "Hello";//全局常量
public abstract void print(); //抽象方法
}
由于接口里面存在有抽象方法,所以接口对象不可能直接使用关键字new进行实例化的操作,所以接口使用原则有:
1.接口必须要有子类,但是此时一个子类可以使用implements关键字实现多个接口;
2.接口的子类(如果不是抽象类),那么必须要覆写接口中的全部抽象方法
3.接口的对象可以利用子类对象的向上转型进行实例化操作
接口实例:
interface A{
public static final String MSG = "hello" ;
public abstract void print() ;
}
interface B {
public abstract void get();
}
class X implements A,B{
public void print(){
System.out.println("A");
}
public void get(){
System.out.println("B");
}
}
public class Demo{
public static void main(String args[]){
X x = new X() ;//实例化
A a = x ;//向上转型
B b = x ;//向上转型
a.print();
b.get();
}
}
上面的实例化代码,改成:
A a = new X();
B b = (B) a ;
b.get();
//System.out.println(a instanceof A);
//System.out.println(a instanceof B);
结果是正确的,后面也返回的true,定义结构上AB没有任何直接联系,但是这两个接口都有同一个子类,千万不要被类型与名称迷惑,new的是X子类,而这个子类也属于B类的对象,只是从代码编写上讲,有点难理解。
2)同时继承接口与抽象类
对于子类而言,除了接口以外,还可能会继承抽象类,那么两个当同时进行时,我们要先使用extends继承,再使用implements实现。
已经定义好了接口A、B,抽象类C;
格式: class X extends C implements A,B { }
3)多个接口定义
一个抽象类可以去继承一个接口,但注意,一个接口可以使用extends关键字同时继承多个接口(但是接口不能继承抽象类).
接口实例:
interface A{
public void funA();
}
interface B{
public void funB();
}
interface C extends A,B {
public void funC();
}
class X implements C {
public void funA ( ) { }
public void funB ( ) { }
public void funC ( ) { }
}
……
从继承关系上讲抽象类的限制比接口多了太多:
1.一个抽象类只能够继承一个抽象的父类,而接口没有这个限制
2.一个子类只能够继承一个抽象类,而却可以实现多个接口
4)内部接口
接口虽然本身概念来说,只能够由抽象方法和全局变量组成,但是所有的内部结构是不受这些限制的,也就是说接口里面可以定义普通内部类、抽象内部类、内部接口。
接口实例:
interface A{
public void funA();
abstract class B {
public abstract void funB() ;
}
}
class X implements A{ //实现了A接口
public void funA(){
System.out.println("hello");
}
class Y extends B{ //内部抽象类的子类
public void funB() {};
}
}
一般不会这样,举个例子而已。。。
在一个接口内部,如果使用了static去定义一个内部接口,那么表示是一个外部接口:
interface A{
public void funA();
static interface B { //外部接口
public void funB() ;
}
}
class X implements A.B { //实现了A接口
public void funB() ;
}
2.标准定义
定义实例:USB设备标准举例
interface USB {
public void start() ;
public void stop() ;
}
class Computer{
public void plugin(USB usb){//插入USB
usb.start();
usb.stop();
}
}
class Flash implements USB{
public void start() {
System.out.println("U盘开始使用");
}
public void stop() {
System.out.println("U盘停止使用");
}
}
class Scan implements USB{
public void start() {
System.out.println("扫描仪开始工作");
}
public void stop(){
System.out.println("扫描仪停止工作");
}
}
public class Test{
public static void main (String args []) {
Computer com = new Computer() ;
com.plugin(new Flash());
com.plugin(new Scan());
}
}
3.工厂设计模式
先来一段普通接口代码:
interface Fruit {
public void eat() ;
}
class Apple implements Fruit {
public void eat() {
System.out.println("eat apple");
}
}
class orange implements Fruit {
public void eat() {
System.out.println("eat orange");
}
}
public class Test{
public static void main(String args[]){
Fruit f = new Apple() ;
f.eat() ;
}
}
这个代码从代码角度看,是没有问题的,但是,从客户端角度看的话,吃apple或者orange 就要 new 不一样的,换来换去麻烦,也可以理解为耦合度太高,直接问题是代码不方便维护。
确认一个代码真的好,有这么几个标准:
1.客户端调用简单,不需要关注具体的细节
2.客户端之外的代码修改,不影响用户的用户,即用户不用担心代码是否变更
那么看下下面这个例子:
interface Fruit {
public void eat() ;
}
class Apple implements Fruit {
public void eat() {
System.out.println("eat apple");
}
}
class Orange implements Fruit {
public void eat() {
System.out.println("eat orange");
}
}
class Factory {
public static Fruit getInstance(String className){
if("apple".equals(className)) {
return new Apple() ;
}else if ("orange".equals(className)) {
return new Orange();
}else {
return null ;
}
}
}
public class Test{
public static void main(String args[]){
Fruit f = Factory.getInstance("apple");
f.eat() ;
}
}
现在客户端不会看到具体的子类,因为所有的接口对象都是通过factory类取得的,如果日后要扩充新的Fruit子类对象,只需要修改Factory就可以了,但是客户端不会发生变化
4.代理设计模式
interface Subject{ //整个操作的核心主题
public void make() ; //核心功能
}
class RealSubject implements Subject {
public void make() {
System.out.println("做什么什么");
}
}
class ProxySubject implements Subject{
private Subject subject ;
//接收一个真实主题的操作对象
public ProxySubject(Subject subject) {
this.subject = subject ;
}
public void prepare() {
System.out.println("准备");
}
public void make() {
this.prepare();
this.subject.make();
this.destroy();
}
public void destroy() {
System.out.println("销毁");
}
}
public class Test {
public static void main(String args[]) {
Subject sub = new ProxySubject(new RealSubject());
sub.make() ; //调用的是代理主题操作
}
}
代理设计模式的核心精髓在于有一个主题操作接口(可能有多种方法),核心业务主题只完成核心功能,而代理主题负责完成所有与核心主题有关的辅助性操作