MST

星途 面试题库

面试题:Java中接口与抽象类在设计模式中的应用区别

请阐述在常见设计模式(如策略模式、模板方法模式)中,Java接口与抽象类分别是如何应用的,它们各自起到什么样不同的作用,举例说明。
45.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

Java接口在常见设计模式中的应用及作用

  1. 策略模式
    • 应用:在策略模式中,定义一个接口,该接口包含一系列相关算法的抽象方法。不同的具体策略类实现这个接口,每个具体策略类实现接口中定义的算法。
    • 作用:接口定义了一系列可替换的行为(算法)的契约,使得系统能够根据不同的场景选择不同的具体策略。这增强了系统的灵活性和可维护性,符合开闭原则,即对扩展开放,对修改关闭。
    • 举例:假设我们有一个电商系统,在计算订单运费时,有多种计算方式,如按重量计费、按订单金额计费等。我们可以定义一个ShippingStrategy接口:
public interface ShippingStrategy {
    double calculateShippingCost(double weight, double orderAmount);
}

然后具体的策略类实现这个接口,如按重量计费的策略:

public class WeightBasedShippingStrategy implements ShippingStrategy {
    @Override
    public double calculateShippingCost(double weight, double orderAmount) {
        return weight * 10; // 每克10元运费示例
    }
}
  1. 模板方法模式:虽然模板方法模式更多使用抽象类,但接口也可在其中辅助定义部分行为。比如在一个数据处理流程中,定义一个DataProcessor接口,包含数据读取、处理和输出的抽象方法,不同的数据处理类实现该接口完成特定数据处理流程。

Java抽象类在常见设计模式中的应用及作用

  1. 模板方法模式
    • 应用:在模板方法模式中,抽象类定义了一个算法的骨架,将一些步骤延迟到子类中实现。抽象类包含抽象方法和具体方法,抽象方法由子类实现,具体方法提供通用的实现逻辑。
    • 作用:通过抽象类,将算法的通用部分和变化部分分离,子类只需关注自己需要实现的部分,避免代码重复,提高代码复用性。同时,也体现了开闭原则。
    • 举例:以制作咖啡和茶的流程为例,制作饮品都有烧水、浸泡原料、倒入杯子等步骤,但浸泡原料方式不同。定义一个Beverage抽象类:
public abstract class Beverage {
    // 模板方法
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
    void boilWater() {
        System.out.println("Boiling water");
    }
    void pourInCup() {
        System.out.println("Pouring into cup");
    }
    abstract void brew();
    abstract void addCondiments();
}

然后具体的CoffeeTea子类继承Beverage并实现抽象方法:

public class Coffee extends Beverage {
    @Override
    void brew() {
        System.out.println("Dripping Coffee through filter");
    }
    @Override
    void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
}
  1. 策略模式:抽象类也可作为策略的基类,在其中定义一些通用的属性和方法,具体策略类继承抽象类。例如,在一个游戏角色行为策略中,定义一个抽象的CharacterStrategy抽象类,包含通用的角色属性和一些可复用的方法,不同的具体行为策略类继承它并实现具体行为。

两者的不同

  • 接口:更强调行为的抽象和契约定义,一个类可以实现多个接口,适合实现多继承的效果,侧重于定义一系列相关但不同实现的行为集合。接口中的方法默认是抽象的,不能有实现代码(Java 8 及以后可定义默认方法,但主要目的也是为了向后兼容)。
  • 抽象类:侧重于代码复用,一个类只能继承一个抽象类。抽象类可以包含抽象方法和具体方法,能够定义一些通用的状态和行为,让子类继承并复用。适用于当一系列类有共同的属性和行为,且需要在抽象层定义骨架逻辑时使用。