MST

星途 面试题库

面试题:Java中抽象类与接口在策略模式中的应用

请阐述在Java策略模式中,抽象类和接口分别在哪些场景下可以作为策略的定义方式?请举例说明两者在策略模式实现中的代码结构差异。
29.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

抽象类作为策略定义方式的场景

  1. 当策略需要有部分通用实现时:如果多个具体策略有一些共同的属性或方法实现,使用抽象类可以将这些通用部分提取出来,避免在具体策略类中重复编写。例如,在一个图形绘制的策略模式中,不同图形(圆形、矩形等)的绘制可能都需要获取画笔相关的操作,这些获取画笔的操作可以放在抽象类中实现。
  2. 当策略需要继承其他类时:Java 不支持多重继承,若策略类需要继承自某个特定类,同时又作为策略定义,此时抽象类是合适的选择。

接口作为策略定义方式的场景

  1. 当策略只关注行为定义,没有通用实现时:如果每个具体策略的实现完全不同,仅仅需要定义一组行为规范,接口是更好的选择。例如,在一个支付策略模式中,微信支付、支付宝支付、银行卡支付等具体实现差异很大,只需要定义统一的支付接口方法,如pay(double amount)
  2. 希望策略具有更高的灵活性和扩展性:接口允许多个类实现,一个类还可以实现多个接口,这使得系统在扩展新策略时更加灵活。

代码结构差异示例

  1. 以抽象类作为策略定义
// 抽象策略类
abstract class DrawStrategy {
    // 通用方法
    protected void getPen() {
        System.out.println("获取画笔");
    }
    // 抽象方法,具体策略实现
    abstract void draw();
}

// 具体策略类 - 绘制圆形
class CircleDrawStrategy extends DrawStrategy {
    @Override
    void draw() {
        getPen();
        System.out.println("绘制圆形");
    }
}

// 具体策略类 - 绘制矩形
class RectangleDrawStrategy extends DrawStrategy {
    @Override
    void draw() {
        getPen();
        System.out.println("绘制矩形");
    }
}

// 上下文类
class DrawingContext {
    private DrawStrategy drawStrategy;
    public DrawingContext(DrawStrategy drawStrategy) {
        this.drawStrategy = drawStrategy;
    }
    public void executeDraw() {
        drawStrategy.draw();
    }
}
  1. 以接口作为策略定义
// 策略接口
interface PayStrategy {
    void pay(double amount);
}

// 具体策略类 - 微信支付
class WeChatPayStrategy implements PayStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount + "元");
    }
}

// 具体策略类 - 支付宝支付
class AlipayPayStrategy implements PayStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount + "元");
    }
}

// 上下文类
class PaymentContext {
    private PayStrategy payStrategy;
    public PaymentContext(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }
    public void executePay() {
        payStrategy.pay(this.amount);
    }
}

从上述代码可以看出,使用抽象类时,具体策略类继承抽象策略类,可以复用抽象类中的通用方法;而使用接口时,具体策略类实现接口,接口中只有方法声明,没有实现,具体策略的实现完全由实现类自行完成。