MST

星途 面试题库

面试题:Java访问者模式与其他设计模式的对比及适用场景分析

在Java开发中,将访问者模式与策略模式、观察者模式进行对比,分析它们在设计意图、结构特点以及适用场景上的差异。请结合具体代码示例说明。
37.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计意图

  • 访问者模式:主要用于分离数据结构和对数据结构中元素的操作。使得新增对数据结构元素的操作变得容易,而不需要修改数据结构本身。例如,一个由多种图形(如圆形、矩形)组成的图形结构,当需要新增计算图形面积、周长等不同操作时,使用访问者模式可在不修改图形类的前提下实现。
// 抽象元素类
abstract class Element {
    public abstract void accept(Visitor visitor);
}
// 具体元素类1
class Circle extends Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
// 具体元素类2
class Rectangle extends Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
// 抽象访问者
interface Visitor {
    void visit(Circle circle);
    void visit(Rectangle rectangle);
}
// 具体访问者1,计算面积
class AreaVisitor implements Visitor {
    @Override
    public void visit(Circle circle) {
        // 计算圆形面积逻辑
    }
    @Override
    public void visit(Rectangle rectangle) {
        // 计算矩形面积逻辑
    }
}
  • 策略模式:定义一系列算法,将每个算法封装起来,并使它们可以相互替换。其目的是让算法的变化独立于使用算法的客户。比如,一个支付系统,有多种支付方式(如微信支付、支付宝支付),每种支付方式就是一个具体策略。
// 抽象策略
interface PaymentStrategy {
    void pay(double amount);
}
// 具体策略1,微信支付
class WeChatPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount);
    }
}
// 具体策略2,支付宝支付
class AlipayPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount);
    }
}
// 上下文
class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    public ShoppingCart(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
    public void pay(double amount) {
        paymentStrategy.pay(amount);
    }
}
  • 观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。例如,新闻发布系统,当有新新闻发布时,所有订阅该新闻的用户会收到通知。
// 抽象主题
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
// 具体主题
class NewsPublisher implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String news;
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(news);
        }
    }
    public void publishNews(String news) {
        this.news = news;
        notifyObservers();
    }
}
// 抽象观察者
interface Observer {
    void update(String news);
}
// 具体观察者,用户
class User implements Observer {
    private String name;
    public User(String name) {
        this.name = name;
    }
    @Override
    public void update(String news) {
        System.out.println(name + " 收到新闻:" + news);
    }
}

结构特点

  • 访问者模式:包含抽象元素、具体元素、抽象访问者和具体访问者。元素类有接受访问者的方法,访问者类有针对不同元素的访问方法。元素结构和操作解耦。
  • 策略模式:由抽象策略、具体策略和上下文组成。上下文持有一个抽象策略的引用,通过组合方式使用具体策略。强调算法的可替换性。
  • 观察者模式:有抽象主题、具体主题、抽象观察者和具体观察者。主题维护观察者列表,通过通知方法告知观察者状态变化。重点在于对象间的依赖关系。

适用场景

  • 访问者模式:适用于数据结构相对稳定,但对数据结构中元素的操作经常变化的场景。例如编译器的语义分析阶段,语法树结构稳定,但不同的语义检查操作可以通过访问者模式实现。
  • 策略模式:当有多种算法变体,并且希望在运行时根据不同情况选择不同算法时使用。比如电商系统中不同促销策略的选择。
  • 观察者模式:用于当一个对象状态改变需要通知多个其他对象,并且这些对象对该状态改变做出响应的场景。如消息推送系统、股票价格监控系统等。