Interface关键字/接口
接口
接口是一种规范,接口本质上也是一个抽象类,不过只包含常量和方法。
接口的特点
1.接口用interface来声明
2.接口中可以声明成员变量,成员变量都是默认public static final修饰的。
3.jdk1.7之前,接口中所有的方法都是抽象方法
4.接口中没有构造器(不能声明构造器)
注意
1.接口可以多继承接口的
2.接口只能被类实现
3.实现接口要重写接口中的所有的抽象方法
4.接口主要是用于被实现的(面向接口编程)
接口和抽象类的区别
- 1,接口和抽象都不能有实例
- 2,抽象类中可以有构造可以有普通方法和普通的成员变量,接口中只能声明静态公共常量(public static final),默认都是抽象方法
- 3,接口是需要被实现的,抽象类是需要被继承的
- 4,抽象类如果子类不想实现抽象类中的方法,那么该子类也必须是抽象类
- 5,接口可以多继承接口,实现类可以多实现接口,抽象类只能单继承
- 6,抽象类是重构的结果,接口是设计的结果
接口的4种实现方式
先解释一下匿名对象和匿名类。
-
匿名对象:匿名对象是没有名字的实体,也就是该实体没有对应的变量名引用,创建的匿名类的对象只能调用一次,匿名对象只在堆内存中开辟空间,而不存在栈内存的引用,而且每次创建匿名对象都是不同的对象。
-
匿名类: 匿名类 匿名类是不能有名称的类,所以没办法引用它们。必须在创建时,作为new语句的一部分来声明它们。匿名类相当于在定义类的同时再新建这个类的实例定义.
若要实现接口,先创建一个接口。
interface Usb{
//数据传输开始的方法
public void start();
//数据传输结束的方法
public void stop();
}
再创建一个类,传入UBS接口的实现类,可以体现接口的多态性(计算机可以加载打印机,U盘等等)
class Computer {
public static void transferData(USB usb) {
usb.start();
System.out.println(" ** 设备运行的过程 ** ");
usb.stop();
}
}
然后就可以实现接口了 main
先创建一个计算机
Computer computer = new Computer();
再传入想运行的设备(将数据线插入USB中)
1.接口的非匿名对象的非匿名实现类
Usb printer = new Printer();
computer.transferData(printer);//传输数据
Printer类是已经创建好的,以下:
class Printer implements USB {
public void start() {
System.out.println("打印机设备开始运作:");
}
public void stop() {
System.out.println("打印机设备停止运作!");
}
}
2,接口的匿名对象的非匿名实现类
computer.transferData(new Flash());
Flash类是已经创建好的,以下:
// 具体的设备U盘
class Flash implements USB {
public void start() { //jdk1.8以后这里不用加@Override
System.out.println("U盘设备开始运作:");
}
public void stop() {
System.out.println("U盘设备停止运作!");
}
}
3,接口的非匿名对象的匿名实现类
USB phone = new USB() {
public void stop() {
System.out.println("电话设备停止运行!");
}
public void start() {
System.out.println("电话设备开始运行");
}
};
computer.transferData(phone);
显然,不需要单独创建Phone类
4,接口的匿名对象的匿名实现类
computer.transferData(new USB(){
public void start() {
System.out.println("电话设备开始运行");
}
public void stop() {
System.out.println("电话设备停止运行!");
}
});
显然,不需要单独创建Phone类,也不需要单独创建phone对象。
最后,匿名实现类适合什么时候用呢??比如,突然,想要运行一下电话设备,但以后再也不运行了,就用这个接口匿名对象类实现。
接口的应用之一:代理模式
- 意图:为其他对象提供一个代理以控制对这个对象的访问。
- 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
- 何时使用:想在访问一个类时做一些控制。
- 如何解决:增加中间层。在代理类中创建代理接口的对象,构造时传入被代理类(实现多态,所以接口类就行),并创建用于控制的方法。
静态代理
先创建代理接口
// 代理接口,可以实现浏览功能
interface NetWork{//网络
public void browse();//浏览
再创建一个被代理类
// 被代理类
class RealServer implements NetWork{
@Override
public void browse() {
System.out.println("上网浏览信息");
}
}
最后创建代理类(四个部分)
- 私有成员:接口对象
- 构造器:传入外界的接口对象,拷贝给成员对象
- 成员方法:随便(安全控制,或者进程外的访问等等)
- 最后,重写接口中的抽象方法
class ProxyServer implements NetWork{
private NetWork netWork;
public ProxyServer( NetWork netWork) {
this.netWork = netWork;
}
public void check() {
System.out.println("网络连接检查");
}
@Override
public void browse() {
check();
netWork.browse();
}
}
最后跑一下
public class ProxyTest {
public static void main(String[] args) {
NetWork net = new ProxyServer(new RealServer());
net.browse();
}
}
运行结果:
网络连接检查
上网浏览信息
接口的应用之二:工厂模式
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。(比如坐出租车时虽然你不知道太白南路怎么去,但告诉司机就行了,他会把你送到)
-
优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
4、实现了创建着和调用者的分离,即创建对象的具体过程屏蔽隔离,提高程序的灵活性 -
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
-
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
面向的对象的设计原则:ocp(开闭原则)
分类:
- 1,简单工厂模式
- 2,工厂方法模式
- 3,抽象工厂模式
核心:实例化对象,用工厂替代new操作
工厂模式的实现
我们将创建一个 Car 接口和实现 Car 接口的实体类。然后定义工厂类 eFactory。
1.创建一个Car 接口
interface Car{
void run();
}
2.实现 Car接口的实体类
class Audi implements Car{
@Override
public void run() {
System.out.println("奥迪run");
}
}
class BYD implements Car{
@Override
public void run() {
System.out.println("BYD run");
}
}
3.定义工厂类 Factory
class Facatory{
public static Car getCar(String type) {
if("奥迪".equals(type)) {
return new Audi();
}else if("比亚迪".equals(type)) {
return new BYD();
}else {
return null;
}
}
}
最后,跑一下
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new Factory();
Car audi = factory.getCar("奥迪");
audi.run();
Car byd = factory.getCar("比亚迪");
byd.run();
}
}
运行结果:
奥迪run
BYD run