Java设计模式:深入理解面向接口编程(那些年的面向接口编程,DIY电脑为例)

面向接口编程(哪些年的面向接口编程)
接口是Java的重要特性之一,在Java8以前,接口可以说是一种方法签名,或者一种行为契约,类实现了某个接口,就需要实现该接口中定义的方法。接口可以认为是一种特殊的抽象类,Java8之前的版本在接口中只能定义常量和抽象方法。实现类实现接口本身也类似于继承,只是继承过来的是行为约束,比如:人打从娘胎里出来就约定了必须具有的行为:吃喝拉撒。Java的接口本身依托于Java的多态机制,以下通过一个列子,说明面向接口编程为何能够提升我们代码的灵活性、可扩展性,并且有效降低代码的耦合。

 1.首先还是简单地介绍下接口的定义(Java8之前的版本,在此不讨论Java8新的default特性)
Java8以前接口的定义如下:

[访问权限] interface 接口名 {

    公开的静态常量列表;

    公开的抽象方法列表;

}

类实现接口:

[访问权限] class 类名称 implements 接口1,接口2{

    //重写接口1中的方法

    //重写接口2中的方法

}

2.学IT行业的同学,尤其是爱打游戏的同学,可能自己组装过电脑,下面通过组装电脑为例,简要地理解面向接口编程的好处

我们都知道现在的电脑主板上提供了很多接口,CPU插口、硬盘插口、内存插口、显卡插口,同一块主板上各类接口,一般都同时支持多种类型的CPU、硬盘和内存和显卡,假如有如下场景:
小哥哥是个游戏高手,手头不太富裕,花了8000块钱配置了一台电脑:

技嘉的主板型号1、I7CPU、512G SSD、8G内存、2G独显

通过半年的省吃俭用,小哥哥终于攒了1万块钱,购买了一块5000块钱的超级显卡,对电脑升级。

试想如果电脑显卡、内存、CPU、硬盘等都是不可插拔的,而是焊接死的,求小哥哥的心理阴影面积。

好下面我们通过组装电脑为例说明面向接口编程的灵活之处,假设电脑只有CPU和硬盘:

定义CPU接口:

/**
 * 定义CPU接口
 * @author liuhaibing
 * @version 1.0  
 */
public interface CPU {
	
	// 面向接口编程:接口其实可以认为是一个标准,一个行为契约
	// 接口的方法默认就是public abstract的
	
	
	void calculate();   // CPU要能计算
}

定义硬盘接口:

/**
 * 定义硬盘接口
 * @author liuhaibing
 * @version 1.0  
 */

public interface Disk {
	
	void storeData(); // 硬盘要能存储数据
}

定义I3CPU类实现了CPU接口:

/**
 * @author liuhaibing  
 * @version 1.0  
 */
public class I3CPU implements CPU{
	
	private double rate = 2.6;

	@Override
	public void calculate() {
		// TODO Auto-generated method stub
		System.out.println("我是i3的CPU I'm running!");
	}
}

定义I7CPU类实现了CPU接口:

/**
 * @author liuhaibing
 * @version 1.0  
 */
public class I7CPU implements CPU{
	
	@Override
	public void calculate() {
		// TODO Auto-generated method stub
		System.out.println("我是i7的CPU I'm running!");
	}

}

定义NormalDisk(机械硬盘了)并实现Disk接口:

/**
 * @author liuhaibing 
 * @version 1.0  
 */
public class NormalDisk implements Disk{
	
	@Override
	public void storeData() {
		// TODO Auto-generated method stub
		System.out.println("我是机械硬盘 I'm running!");
	}

}

定义SSDDisk(固态硬盘类)并实现Disk接口:

/**
 * @author liuhaibing
 * @version 1.0  
 */
public class SSDDisk implements Disk{

	@Override
	public void storeData() {
		// TODO Auto-generated method stub
		System.out.println("我是固态硬盘 I'm running!");
	}

}

定义电脑类:

/**
 * @author liuhaibing
 * @version 1.0  
 */
public class Computer {
	
	// 在这里定义的是接口,不是具体的实现类,所以就达到了面向接口编程的目的,这样电脑不
	// 直接依赖具体的硬盘或CPU的实现
	private Disk disk;  // 硬盘插口  computer关联了disk和cpu
	private Disk disk2; // 硬盘插口2
	private CPU  cpu;    // CPU插口
	
	// 以下注释的定义代是非面向接口编程,电脑和具体的硬盘绑定了,构成了强耦合
	// private I7CPU cpu;
	// private SSDDisk disk; 耦合
	
	// 标准面向接口编程的构造方法,组装的时候使用接口作为电脑类构造方法的形参,从而达到解耦合
	public Computer(Disk disk, CPU cpu, Disk disk2) {
		this.disk = disk;
		this.cpu  = cpu;
		this.disk2 = disk2;
	}
	
	// 如果不用面向接口编程,组装不同的电脑要不同的构造方法,类似就像是为新开一条生产线
	// 代码也和具体的实现类产生了耦合
	//public Computer(SSDDisk disk, I3CPU cpu, NormalDisk disk2) {
	
	//}
	
	// 如果不用面向接口编程,组装不同的电脑要不同的构造方法,类似就像是为新开第二条生产线
	//public Computer(SSDDisk disk, I7CPU cpu, Disk disk2) {
	
	//}
	
	// 启动电脑
	public void startComputer() {
		if(disk != null && cpu !=null) {
			cpu.calculate();
			disk.storeData();
		}else {
			System.out.println("启动失败");
		}
	}
}

下面开始组装不同的电脑:

/**
 * @author liuhaibing
 * @version 1.0  
 */
public class DiyComputer{

	/**  
	 * @author liuhaibing
	 * @version 1.0 
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 第一台电脑的配置
		Disk disk = new SSDDisk(); //多态:接口的引用引用了实现类的对象
		CPU  cpu = new I3CPU();
		
		// diy第一台电脑
		Computer cp = new Computer(disk, cpu, null);
		cp.startComputer();
		
		// 第二台电脑的配置
		Disk disk2 = new SSDDisk();
		CPU  cpu2 = new I7CPU();
		
		// diy第二台电脑
		Computer cp2 = new Computer(disk2, cpu2, null);
		cp2.startComputer();
	}

}

 

你可能感兴趣的:(Java,面向接口编程)