设计模式概述 - 适配器 & 备忘录 & 组合 & 迭代器
适配器模式简述
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而无法一起工作的类可以协同工作。
角色
- 目标接口(Target):客户端所期望的接口。
- 适配者(Adapter):实现目标接口,并持有一个被适配的对象的引用。
- 被适配者(Adaptee):需要适配的类,通常具有一个与目标接口不兼容的接口。
优点
- 解耦:适配器模式将客户端与被适配者解耦。
- 增强复用性:可以在不修改已有代码的情况下,使用适配器将现有类与新接口兼容。
- 灵活性:适配器可以通过组合的方式灵活地适配不同的接口。
缺点
- 增加复杂性:引入适配器可能会增加系统的复杂性。
- 性能开销:适配器模式可能会引入额外的性能开销。
示例代码
// 目标接口
interface Target {
void request();
}
// 被适配者
class Adaptee {
public void specificRequest() {
System.out.println("Called specificRequest() from Adaptee.");
}
}
// 适配器
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest(); // 调用被适配者的方法
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request(); // 通过适配器调用被适配者的方法
}
}
备忘录模式简述
备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不暴露对象内部状态的情况下,保存和恢复对象的状态。备忘录模式通常用于实现撤销功能,能够在不破坏封装性的前提下,保存对象的历史状态。
角色
- 发起人(Originator):需要保存其内部状态的对象。
- 备忘录(Memento):用于存储发起人的内部状态,但不允许外部访问。
- 负责人(Caretaker):负责管理备忘录对象,保存和恢复发起人的状态。
优点
- 封装性:允许对象在不暴露其内部状态的情况下保存和恢复状态。
- 简化代码:通过使用备忘录,撤销和恢复操作的实现变得简单明了。
- 支持多次恢复:可以保存多个状态的备忘录,支持多次恢复。
缺点
- 内存消耗:如果需要保存多个状态的备忘录,可能会消耗较多的内存。
- 管理复杂性:在管理大量备忘录时,可能会增加系统的复杂性。
示例代码
// 备忘录类
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人类
class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("Originator: Setting state to " + state);
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
System.out.println("Originator: State restored to " + state);
}
}
// 负责人类
class Caretaker {
private Memento memento;
public void saveState(Originator originator) {
memento = originator.saveStateToMemento();
}
public void restoreState(Originator originator) {
originator.getStateFromMemento(memento);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State 1");
caretaker.saveState(originator);
originator.setState("State 2");
caretaker.restoreState(originator); // 恢复到State 1
}
}
组合模式简述
组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树形结构以表示部分-整体的层次关系。组合模式使得客户端对单个对象和组合对象的使用具有一致性,从而简化了客户端的代码。
角色
- 组件(Component):定义树形结构中所有对象的共同接口,可以是叶子节点或复合节点。
- 叶子(Leaf):实现组件接口的具体对象,表示树的叶子节点。
- 复合节点(Composite):实现组件接口并持有子组件的引用,表示树的非叶子节点。
优点
- 简化客户端代码:客户端可以使用统一的接口处理单个对象和组合对象,简化了代码。
- 易于扩展:可以自由地添加新叶子和复合节点,符合开放-封闭原则。
- 树形结构:适合表示部分-整体的层次结构,易于管理和维护。
缺点
- 设计复杂性:组合模式可能导致设计过于复杂,尤其是在层次结构较深时。
- 性能开销:在某些情况下,可能会引入额外的性能开销,特别是在处理大量节点时。
示例代码
import java.util.ArrayList;
import java.util.List;
// 组件接口
interface Component {
void operation();
}
// 叶子节点
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Leaf: " + name);
}
}
// 复合节点
class Composite implements Component {
private List<Component> children = new ArrayList<>();
private String name;
public Composite(String name) {
this.name = name;
}
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
System.out.println("Composite: " + name);
for (Component child : children) {
child.operation(); // 递归调用
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Composite root = new Composite("Root");
Composite composite1 = new Composite("Composite 1");
Composite composite2 = new Composite("Composite 2");
Leaf leaf1 = new Leaf("Leaf 1");
Leaf leaf2 = new Leaf("Leaf 2");
Leaf leaf3 = new Leaf("Leaf 3");
composite1.add(leaf1);
composite1.add(leaf2);
composite2.add(leaf3);
root.add(composite1);
root.add(composite2);
root.operation(); // 执行操作
}
}
迭代器模式简述
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供一种方法来顺序访问一个集合对象中的元素,而不暴露该对象的内部表示。迭代器模式使得集合的遍历变得更加灵活,能够支持不同的遍历方式。
角色
- 迭代器(Iterator):定义访问和遍历元素的接口。
- 具体迭代器(ConcreteIterator):实现迭代器接口,维护对集合的引用,并实现具体的遍历逻辑。
- 聚合(Aggregate):定义创建迭代器的接口。
- 具体聚合(ConcreteAggregate):实现聚合接口,返回具体的迭代器。
优点
- 封装性:迭代器模式将集合的遍历逻辑与集合的内部结构分离,提升了封装性。
- 支持多种遍历方式:可以为同一集合提供多种不同的迭代方式。
- 简化客户端代码:客户端可以通过迭代器接口轻松遍历集合,代码更加简洁。
缺点
- 增加复杂性:引入迭代器可能会增加系统的复杂性,特别是在需要支持多种迭代器时。
- 性能开销:在某些情况下,使用迭代器可能会引入额外的性能开销。
示例代码
import java.util.ArrayList;
import java.util.List;
// 迭代器接口
interface Iterator<T> {
boolean hasNext();
T next();
}
// 聚合接口
interface Aggregate<T> {
Iterator<T> createIterator();
}
// 具体迭代器
class ConcreteIterator<T> implements Iterator<T> {
private List<T> items;
private int position = 0;
public ConcreteIterator(List<T> items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.size();
}
@Override
public T next() {
return items.get(position++);
}
}
// 具体聚合
class ConcreteAggregate<T> implements Aggregate<T> {
private List<T> items = new ArrayList<>();
public void add(T item) {
items.add(item);
}
@Override
public Iterator<T> createIterator() {
return new ConcreteIterator<>(items);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
aggregate.add("Item 1");
aggregate.add("Item 2");
aggregate.add("Item 3");
Iterator<String> iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}