这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
抽象类
抽象类不允许被实例化,只能被继承,所以我们不能通过 new 来创建抽象类的实例。
抽象类可以包含属性和方法,方法必须要有抽象方法,只有含有抽象方法的类才叫做抽象类。
子类继承抽象类,必须实现抽象类中所有的抽象方法。
接口
抽象类本身也是类,只不过是更加抽象的类,而接口就更加牛逼了,比抽象类还要抽象,很多地方都会说抽象类和接口的区别在于 is-a 和 has-a 的区别,大家自己感受一下即可。
接口可以理解为是一种协议,一种标准,我只负责定义,不负责实现,然而在 Java 8 接口中也能定义 default 的方法了。
像我们常见用 repository 层,就会定义一套接口,而 service 层在使用的时候不需要知道具体的实现是怎么样的,底层的数据库是 MySQL,Oracle ,甚至是 Redis 这些都不重要。
抽象类和接口的使用
抽象类在使用的时候需要注意,因为所有的子类都需要实现其所有的抽象方法,所以在定义的时候,一定要保证是父子类的关系,且抽象类中的方法不易过多,而接口的定义,就是为了定义某种标准,可能是数据交互的标准,子类需要实现接口就代表子类拥有了某种能力。
Java 中虽然不支持多重继承,但是我们可以通过多重实现来达到相似的功能。抽象类多用于模板方法,对模板中某一部分进行抽象,而接口则是完全的抽象。
抽象类的应用 - 模板设计模式
模板设计模式就是指固定的套路 。假如你有如下需求 ,计算代码的运行时间 。套路就是记录开始时间 ,运行方法 ,记录结束时间 ,最后一减得出结果 。可以像这样实现 。
public abstract class SupClass {
public abstract void run();
//这就是一个模板,限定为 final 防止子类重写该方法。
public final void calculateTime(){
long l1 = System.currentTimeMillis();
run();
long l2 = System.currentTimeMillis();
long time = l2 - l1;
System.out.println("运行时间为 " + time + " 毫秒。");
}
}
public class Sub1Class extends SupClass{
@Override
public void run() {
System.out.println("在计算 Sub1Class 的 run 方法执行时间。。。");
long sum = 0;
for (int i = 0; i < 1000000000; i++) {
sum = sum + i;
}
}
}
public class Sub2Class extends SupClass{
@Override
public void run() {
System.out.println("在计算 Sub2Class 的 run 方法执行时间。。。");
long sum = 0;
for (int i = 0; i < 10000000; i++) {
sum = sum + i;
}
}
}
// 测试代码
public class TemplateTest {
public static void main(String[] args) {
SupClass class1 = new Sub1Class();
class1.calculateTime();
SupClass class2 = new Sub2Class();
class2.calculateTime();
}
}
复制代码
接口的应用 - 工厂模式
在工厂模式中 ,我们在创建对象时不会对客户端暴露创建逻辑 ,并且是通过使用一个共同的接口( Car )来指向新创建的对象 。这就是一种创建类的方法 。主要体现在工厂中获取对象的方法的内部逻辑 。像下面示例中的 getCar 方法 。
public interface Car {
void run();
}
public class BaoMa implements Car{
@Override
public void run() {
System.out.println("我在 BaoMa 里笑。");
}
}
public class BigCar implements Car{
@Override
public void run() {
System.out.println("我是 BigCar ,我不怕撞!");
}
}
public class SmallCar implements Car {
@Override
public void run() {
System.out.println("我是 SmallCar ,看起来精致!");
}
}
/**
* 工厂决定以何种形式创建对象,为什么叫工厂,也就是因为,对象如何产生是在这里决定的。
*
*/
public class CarFactory {
// 这是重点呀,返回的都是同一个接口。这也是多态的体现 向上转型。
public Car getCar(String type){
if(type == null){
return null;
}
if(type.equalsIgnoreCase("SMALLCAR")){
return new SmallCar();
} else if(type.equalsIgnoreCase("BIGCAR")){
return new BigCar();
} else if(type.equalsIgnoreCase("BAOMA")){
return new BaoMa();
}
return null;
}
}
// 测试类
public class FactoryTest {
public static void main(String[] args) {
CarFactory factory = new CarFactory();
Car car = factory.getCar("smallcar");
car.run();
Car car2 = factory.getCar("bigcar");
car2.run();
Car car3 = factory.getCar("baoma");
car3.run();
}
}
我是 SmallCar ,看起来精致!
我是 BigCar ,我不怕撞!
我在 BaoMa 里笑。
复制代码
近期评论