行为型软件设计模式
概述
行为型设计模式是软件设计模式中的一类,用于处理对象之间的交互和通信。这些模式关注的是对象之间的行为和职责分配。以下是几种常见的行为型设计模式:
-
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,当一个对象的状态发生变化时,其依赖对象将自动收到通知并进行相应的更新。
-
策略模式(Strategy Pattern):定义了一系列算法,并将其封装在可互换的策略对象中,使得算法的选择可以独立于使用它们的客户端。
-
迭代器模式(Iterator Pattern):提供一种顺序访问聚合对象中各个元素的方法,而无需暴露聚合对象的内部表示。
-
命令模式(Command Pattern):将请求封装成对象,使得可以将不同的请求、队列或者日志来参数化其他对象,并且能够支持撤销操作。
-
状态模式(State Pattern):允许对象在内部状态改变时改变它的行为,看起来就像是改变了它的类。
-
责任链模式(Chain of Responsibility Pattern):将请求的发送者和接收者解耦,使得多个对象都有机会处理请求,将这些对象连接成一条链,并沿着这条链传递请求,直到有对象处理它。
-
模板方法模式(Template Method Pattern):定义了一个算法的骨架,将一些步骤的具体实现延迟到子类中。
-
访问者模式(Visitor Pattern):定义了对某个对象结构中各元素的操作,可以在不改变元素类的前提下定义新的操作。
这些行为型设计模式提供了一些通用的解决方案,可以帮助开发人员更好地组织和管理对象之间的交互,使得系统更加灵活、可扩展和易于维护。不同的模式适用于不同的场景,开发人员可以根据具体需求选择合适的设计模式来解决问题。
动机
行为型软件设计模式关心算法和对象之间的责任分配,不仅是描述对象或类模式,更加侧重描述它们之间的通信模式
内容
迭代器模式抽象了访问和遍历一个集合中的对象的方式
访问者模式封装了分布于多个类之间的行为
中介者模式通过在对象间引入一个中介对象,避免对象间的显式引用
策略模式将算法封装在对象中,这样可以方便指定或改变一个对象使用的算法
状态模式封装了兑现过的状态,使得当对象的状态发生变化时,该对象可以改变自身的行为
一、迭代器模式
概念
怎样遍历一个聚合对象,又不需要了解聚合对象的内部结构,还能够提供多种不同的遍历方式?
迭代器模式的关键思想是
将对列表的访问和遍历从列表对象中分离出来,放入一个独立的迭代对象中
代码
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供一种顺序访问聚合对象中各个元素的方法,而无需暴露聚合对象的内部表示。迭代器模式将遍历聚合对象的责任分离出来,使得聚合对象和迭代器对象可以独立地变化。
下面是一个简单的迭代器模式的代码示例,以便更好地理解:
// 定义迭代器接口
public interface Iterator {
boolean hasNext();
Object next();
}
// 定义具体的聚合对象
public class ConcreteAggregate implements Iterable {
private List<Object> elements = new ArrayList<>();
public void addElement(Object element) {
elements.add(element);
}
public Object getElement(int index) {
return elements.get(index);
}
public int getSize() {
return elements.size();
}
// 返回迭代器对象
@Override
public Iterator iterator() {
return new ConcreteIterator(this);
}
}
// 定义具体的迭代器对象
public class ConcreteIterator implements Iterator {
private ConcreteAggregate aggregate;
private int index;
public ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
this.index = 0;
}
// 判断是否还有下一个元素
@Override
public boolean hasNext() {
return index < aggregate.getSize();
}
// 返回当前元素并移动到下一个位置
@Override
public Object next() {
if (hasNext()) {
return aggregate.getElement(index++);
}
return null;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcreteAggregate aggregate = new ConcreteAggregate();
aggregate.addElement("Element 1");
aggregate.addElement("Element 2");
aggregate.addElement("Element 3");
Iterator iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
在上述示例中,迭代器模式包括以下几个关键组件:
-
迭代器接口(Iterator):定义了迭代器的通用操作,例如
hasNext()
方法用于判断是否还有下一个元素,next()
方法用于返回当前元素并移动到下一个位置。 -
具体聚合对象(ConcreteAggregate):具体的聚合对象实现了
Iterable
接口,并在iterator()
方法中返回了具体的迭代器对象。 -
具体迭代器对象(ConcreteIterator):具体的迭代器对象实现了迭代器接口,并通过聚合对象来遍历聚合对象中的元素。
在客户端代码中,我们首先创建一个具体聚合对象(ConcreteAggregate
),并添加一些元素。然后通过调用iterator()
方法获取具体的迭代器对象(ConcreteIterator
),使用迭代器对象遍历聚合对象中的元素并打印出来。
迭代器模式的优点包括:
- 分离了聚合对象和遍历逻辑,使得
聚合对象的结构和遍历算法可以独立变化。
- 简化了聚合对象的接口,客户端无需关心聚合对象的内部结构,只需要通过迭代器进行遍历操作。
- 支持多种遍历方式,可以定义不同类型的迭代器来满足不同的遍历需求。
总之,迭代器模式通过将遍历操作从聚合对象中分离出来,提供了一种统一的访问元素的方式,并且使得聚合对象和迭代器对象可以独立地变化。这样可以简化代码结构,提高代码的可读性和可维护性。
类图
实例一:
迭代器里的四个方法(一般)
1.boolean hasNext()
2.next()
3.remove()
4.getNumOfItems()
实例二:
优缺点
优点:
- 迭代器模式支持以不同的方式遍历同一个聚合,复杂的聚合可用多种方式进行遍历。
- 满足“开闭原则”的要求。
- 迭代器简化了聚合的接口。有了迭代器的遍历接口,聚合本身就不需要类似的遍历接口了,这样就简化了聚合的接口。
缺点:
- 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类
- 类的个数成对增加,这在一定程度上增加了系统的复杂性。
模式适用环境
在以下情况下可以使用迭代器模式:
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 需要为聚合对象提供多种遍历方式。
- 为遍历不同的聚合结构提供一个统一的接口。
课程作业
在例4.4中增加一个迭代器,按照斜对角线迭代遍历矩阵。请画出类图