整理好了!2024年最常见 20 道设计模式面试题(五)

上一篇地址:整理好了!2024年最常见 20 道设计模式面试题(四)-CSDN博客

九、什么是命令模式?它如何帮助实现解耦?

命令模式(Command Pattern)是一种行为设计模式,它将一个请求或操作封装为一个对象。这种模式的主要目的是将发起请求的对象与执行请求的对象解耦,从而让不同的请求、队列或者日志请求以及操作的撤销等操作能够统一处理。

命令模式的组成部分:

  1. 命令接口(Command Interface):定义了执行命令的方法,所有命令类都必须实现这个接口。
  2. 具体命令(Concrete Command):实现命令接口,对应具体的操作。
  3. 调用者(Invoker):要求命令对象执行请求。
  4. 接收者(Receiver):知道如何实施与执行一个请求相关的操作。
  5. 客户端(Client):创建具体命令对象,并且设置它的接收者。

命令模式如何帮助实现解耦:

  1. 请求者与执行者的解耦:命令模式通过将请求封装为对象,使得请求者和执行者之间没有直接的联系。请求者只需要知道命令接口,而不需要了解具体的命令实现。

  2. 扩展性:当需要添加新的命令时,只需增加一个新的具体命令类,而不需要修改现有的代码。这符合开闭原则(对扩展开放,对修改封闭)。

  3. 参数化方法调用:命令模式允许将方法调用的参数进行参数化,这使得可以在不同的时间、不同的环境中执行相同的请求。

  4. 支持撤销操作:通过维护命令的历史记录,可以实现撤销功能。每个命令对象都可以存储足够的状态信息,以便可以恢复到之前的状态。

  5. 支持日志记录:命令对象可以很容易地被记录到日志中,因为它们是对象,可以被序列化和存储。

  6. 支持事务:如果需要,可以设计命令对象来支持事务性操作,确保操作的原子性。

应用场景:

  • 需要对操作进行排队、记录、撤销或重做的场景,如文本编辑器。
  • 需要支持事务性操作的场景。
  • 需要将操作和调用操作的对象解耦的场景。

示例:

假设有一个简单的文本编辑器,它支持撤销和重做操作。使用命令模式,我们可以定义一个命令接口,比如 EditCommand,然后为每个编辑操作(如插入文本、删除文本)创建具体命令类,如 InsertCommandDeleteCommand。编辑器作为调用者,根据用户的操作来创建相应的命令对象,并执行它们。同时,编辑器可以维护一个命令历史记录,以便实现撤销和重做功能。

通过这种方式,命令模式提供了一种灵活、可扩展的方式来处理请求和操作,同时保持了系统的解耦和模块化。

十、迭代器模式是如何遍历一个集合的元素的?

迭代器模式(Iterator Pattern)是一种行为设计模式,它允许在不暴露其底层表示的情况下,顺序访问一个聚合对象中的各个元素。迭代器模式定义了一种方法来顺序访问一个聚合对象中的所有元素,而不依赖于聚合对象的特定类。

迭代器模式的组成部分:

  1. 迭代器接口(Iterator Interface):定义了迭代器的基本操作,如hasNext()(检查是否有下一个元素)和next()(返回下一个元素)。
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,维护遍历过程中的当前位置。
  3. 聚合接口(Aggregate Interface):定义了创建迭代器的方法,通常是一个createIterator()方法。
  4. 具体聚合(Concrete Aggregate):实现聚合接口,返回一个与该具体聚合相关的迭代器实例。

迭代器模式如何遍历集合元素:

  1. 创建聚合对象:首先,你需要有一个聚合对象,它包含了需要遍历的元素集合。

  2. 创建迭代器对象:通过聚合对象的createIterator()方法,创建一个迭代器对象。

  3. 使用迭代器遍历:使用迭代器对象的hasNext()方法检查是否还有元素可以遍历,如果返回true,则使用next()方法获取下一个元素。

  4. 循环遍历:重复步骤3,直到hasNext()返回false,表示所有元素已经被遍历完毕。

迭代器模式的优点:

  • 抽象性:迭代器模式将集合对象的遍历过程抽象化,使得遍历过程与具体的集合类解耦。
  • 灵活性:可以为不同的集合对象定义不同的迭代器,实现不同的遍历策略。
  • 扩展性:在不修改现有代码的情况下,可以很容易地添加新的迭代器类。
  • 安全:迭代器模式可以保护集合的内部结构,防止外部代码直接访问和修改集合的内部状态。

应用场景:

  • 当需要为一个聚合对象提供多种遍历方式时。
  • 当需要在遍历过程中访问聚合对象的内部状态时。
  • 当需要在遍历过程中修改聚合对象时。

示例:

假设有一个书籍集合,我们想要遍历这个集合,打印每本书的标题。使用迭代器模式,我们可以这样实现:

// 聚合接口
interface BookAggregate {
    Iterator createIterator();
}

// 具体聚合
class BookCollection implements BookAggregate {
    private List<Book> books;

    // 创建迭代器
    public Iterator createIterator() {
        return new BookIterator(this);
    }
}

// 迭代器接口
interface Iterator {
    boolean hasNext();
    Book next();
}

// 具体迭代器
class BookIterator implements Iterator {
    private BookCollection collection;
    private int currentIndex = 0;

    public BookIterator(BookCollection collection) {
        this.collection = collection;
    }

    public boolean hasNext() {
        return currentIndex < collection.books.size();
    }

    public Book next() {
        return collection.books.get(currentIndex++);
    }
}

// 客户端代码
BookCollection collection = new BookCollection();
// 填充集合
Iterator iterator = collection.createIterator();
while (iterator.hasNext()) {
    Book book = iterator.next();
    System.out.println(book.getTitle());
}

通过这种方式,迭代器模式提供了一种统一的方法来遍历不同类型的集合,同时保持了代码的灵活性和扩展性。

  • 32
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值