定义
接口可以理解为一个纯粹的抽象类(最原始的定义,接口之中是只包含抽象方法与全局常量的)但是从JDK1.8开始由于引入了Lambda表达式的概念,所以接口的定义也得到了加强,除了抽象方法与全局常量之外,还可以定义普通方法或静态方法,如果从设计本身的角度来讲,接口之中的组成还是应该以抽象方法和全局常量为主。在Java中接口主要使用interface关键字进行定义,由于类名称与接口名称的定义要求相同,所以为了区分出接口,接口名称前往往会加入字母I。
public interface IMessage {
public static final String INFO = "www.kuiyang.com";
public abstract String getInfo();
}
但是现在很明显的问题出现了,此时的接口肯定无法直接产生实例化对象,所以对于接口的使用原则如下:
‒ 接口需要被接口实现(implements),一个子类可以实现多个父接口;
‒ 子类(如果不是抽象类)那么一定要覆I写接口之中的全部抽象方法;
‒ 接口对象可以利用子类对象的向上转型进行实例化
class MessageImpl implements IMessage{
// 实现了接口
public String getInfo(){
return "得到一个消息,秘密的消息,有人胖了(不是我)";
}
}
public class JavaDemo{
public static void main(String args[]){
IMessage msg = new MessageImpl();
System.out.println(msg.getInfo());
System.out.println(IMessage.INFO);// 直接输出全局常量
}
}
以上是接口的基本使用,但是在Jva里面之所以使用接口主要目的是一个子类可以实现多个接口,利用接口可以实现多继承的概念
interface IMessage {
// 定义一个接口
public static final String INFO = "www.mldn.cn"; // 全局常量
public abstract String getInfo(); // 抽象方法
}
interface IChannel {
public abstract boolean connect(); // 定义抽象方法
}
class MessageImpl implements IMessage, IChannel {
// 实现了接口
public String getInfo() {
if (this.connect()) {
return "得到一个消息,秘密的消息,有人胖了(不是我)";
}
return "通道创建失败,无法获取消息";
}
public boolean connect() {
System.out.println("消息发送通道已经成功建立");
return true;
}
}
public class JavaDemo {
public static void main(String args[]) {
IMessage msg = new MessageImpl();
System.out.println(msg.getInfo());
}
}
此时MessageImpl子类的对象可以任意的实现父接口的转换
interface IMessage {
// 定义一个接口
public static final String INFO = "www.mldn.cn"; // 全局常量
public abstract String getInfo(); // 抽象方法
}
interface IChannel {
public abstract boolean connect(); // 定义抽象方法
}
class MessageImpl implements IMessage, IChannel {
// 实现了接口
public String getInfo() {
if (this.connect()) {
return "得到一个消息,秘密的消息,有人胖了(不是我)";
}
return "通道创建失败,无法获取消息";
}
public boolean connect() {
System.out.println("消息发送通道已经成功建立");
return true;
}
}
public class JavObject类对象可以接收所有数据类型,包括基本数据类型,类对象,接口对象,数组aDemo {
public static void main(String args[]) {
IMessage msg = new MessageImpl();
IChannel chl = (IChannel)msg;
System.out.println(chl.connect());
}
}
在Java程序里面接口是不允许去继承父类的,所以接口绝对不会是Object的子类,但是根据之前的分析可以发现MessageImpl是Object子类,所以接口一定可以通过Object接收,Object可以接收一切引用对象()
interface IMessage {
// 定义一个接口
public static final String INFO = "www.mldn.cn"; // 全局常量
public abstract String getInfo(); // 抽象方法
}
interface IChannel {
public abstract boolean connect(); // 定义抽象方法
}
class MessageImpl implements IMessage, IChannel {
// 实现了接口
public String getInfo() {
if (this.connect()) {
return "得到一个消息,秘密的消息,有人胖了(不是我)";
}
return "通道创建失败,无法获取消息";
}
public boolean connect() {
System.out.println("消息发送通道已经成功建立");
return true;
}
}
public class JavaDemo {
public static void main(String args[]) {
IMessage msg = new MessageImpl();
Object obj = msg; // 向上转型
IChannel chan = (IChannel)obj; // 是同一个子类
System.out.println(chan.connect());
}
}
注意:
1.虽然接口无法去继承一个父类,但是一个接口却可以通过extends实现若干个父接口,此时可以称为接口多重继承(多继承)
2.方法不写访问权限也是public,不是default,所以覆写的时候只能够使用public - 感觉没用,写全就行。但是可以省掉接口中抽象方法的abstract。
3.在实际开发之中,接口的时候往往有三种形式:
‒ 进行标准设置
‒ 表示一种操作的能力
‒ 暴露远程方法视图,这个一般都在RPC分布式开发中使用
工程实现模式
以JVM设计为例,Java实现可移植性的关键在于:JVM,而JVM的核心原理:利用一个虚拟机来运行Java程序,所有的程序并不与具体的操作系统有任何关联,而是由JVM来进行匹配,所以得出的结论:良好的设计应该避免耦合
interface IFood{ // 定义一个食物的标准
public void eat(); // 吃
}
class Bread implements IFood { // 定义一种食物
public void eat(){
System.out.println("吃面包");
}
}
class Milk implements IFood { // 定义一种食物
public void eat(){
System.out.println("喝牛奶");
}
}
class Factory{
public static IFood getInstance(String className){
if("bread".equals(className)){
return new Bread();
}else if("Milk ".equals(className)){
return new Milk();
}else{
return null ;
}
}
}
public class JavaDemo{
public static void main(String args[]){
IFood food= Factory.getInstance(args[0]); // 初始化参数
food.eat();
}
}
代理模式
代理设计模式的主要功能是可以帮助用户将所有的开发注意力只集中在核心业务功能的处理上
interface IEat{
public void get();
}
class EatReal implements IEat{
public void get(){
System.out.println("[真实主题]得到一份食物,而后开始品尝美食");
}
}
class EatProxy implements IEat{// 服务代理
private IEat eat; // 为吃服务
public EatProxy(IEat eat){// 一定要有一个代理项
this.eat = eat ;
}
public void get(){
this.prepare();
this.eat.get();
this.clear();
}
public void prepare(){//准备过程
System.out.println("[代理主题]1.精心购买食材");
System.out.println("[代理主题]2.小心处理食材");
}
public void clear(){
System.out.println("[代理主题]3.收拾碗筷");
}
}
public class JavaDemo{
public static void main(String args[]){
IEat eat = new EatProxy(new EatReal());
eat.get();
}
}
一个接口提供有两个子类,其中一个子类是真实业务操作类,另外一个主题是代理业务操作类,没有代理业务操作,真实业务无法进行
接口和抽象类的区别
在实际的开发之中可以发现抽象类和接口的形式是非常相似的,这一点从JDK1.8开始实际上就特别的明显了,因为在JDK1.8里面接口也可以定义default或static方法了,但是这两者依然是有明显的定义区别的:
NO | 区别 | 抽象类 | 接口 |
---|---|---|---|
1 | 定义 | abstract class 抽象类名称{} | interface发接口名称{} |
2 | 组成 | 构造,普通,静态方法,全局常量,成员,static方法 | 抽象方法,全局常量,普通方法,static方法 |
3 | 权限 | 可以使用各种权限定义 | public |
4 | 子类使用 | 子类通过extends关键字可以继承一个抽象类 | 子类使用implements关键字实现多个接口 |
5 | 两者关系 | 抽象类可以实现若干接口 | 接口不允许继承抽象类,但是允许继承多个父接口 |
6 | 使用 | 1. 抽象类或接口必须定义子类 | 子类一定要覆写抽象类或接口中大的全部抽象方法 |
当我们抽象类和接口都可以使用的情况下优先要考虑接口,因为接口可以避免子类的单继承局限 | |||
另外从一个正常的设计角度而言,也需要先从接口来进行项目的整体设计。 |