🚪 传送门:🕺 行为型设计模式:对象协作的舞蹈家(中)
🤝 第八部分:中介者模式(Mediator Pattern)
🤝 中介舞者的登场 🤝
┌─────────────────────────────────────┐
│ 🤝 中介者:我是对象交互协调员! │
│ │
│ 👤 用户A:"我要发消息给用户B!" │
│ 🤝 中介者:"我来协调交互!" │
│ 👤 用户B:"我要回复用户A!" │
│ 🤝 中介者:"继续协调交互!" │
│ │
│ 💡 核心思想:集中控制交互 │
└─────────────────────────────────────┘
🏗️ 中介者模式UML类图
⏱️ 中介者模式时序图
8.1 🎭 什么是中介者模式?
一句话理解:通过中介者集中管理对象间的交互,降低耦合度!
定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用。
应用场景:聊天系统、事件总线、服务注册中心、GUI组件交互、工作流引擎
8.2 🛠️ 中介者模式的实现
8.2.1 🏗️ 基本结构
💡 小贴士:中介者模式就像聊天室,所有用户通过中介者进行通信,避免直接耦合!
核心组件:
- Mediator(中介者):定义对象间通信的接口
- ConcreteMediator(具体中介者):实现中介者接口
- Colleague(同事):需要通信的对象
- ConcreteColleague(具体同事):实现同事接口
8.2.2 🚀 多种实现方式
实现方式 | 特点 | 推荐度 |
---|---|---|
简单中介者 | 一对一交互协调 | ⭐⭐⭐⭐ |
复杂中介者 | 多对多交互协调 | ⭐⭐⭐⭐⭐ |
事件中介者 | 基于事件的松耦合 | ⭐⭐⭐⭐⭐ |
8.2.1 🤝 简单中介者实现
// 简单中介者:一对一交互协调
public interface SimpleMediator {
void send(String message, SimpleColleague colleague);
}
public abstract class SimpleColleague {
protected SimpleMediator mediator;
public SimpleColleague(SimpleMediator mediator) {
this.mediator = mediator;
}
public abstract void send(String message);
public abstract void receive(String message);
}
public class SimpleColleagueA extends SimpleColleague {
private String name;
public SimpleColleagueA(String name, SimpleMediator mediator) {
super(mediator);
this.name = name;
}
@Override
public void send(String message) {
System.out.println(name + " 发送消息: " + message);
mediator.send(message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " 收到消息: " + message);
}
public String getName() {
return name;
}
}
public class SimpleColleagueB extends SimpleColleague {
private String name;
public SimpleColleagueB(String name, SimpleMediator mediator) {
super(mediator);
this.name = name;
}
@Override
public void send(String message) {
System.out.println(name + " 发送消息: " + message);
mediator.send(message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " 收到消息: " + message);
}
public String getName() {
return name;
}
}
public class SimpleConcreteMediator implements SimpleMediator {
private SimpleColleagueA colleagueA;
private SimpleColleagueB colleagueB;
public void setColleagueA(SimpleColleagueA colleagueA) {
this.colleagueA = colleagueA;
}
public void setColleagueB(SimpleColleagueB colleagueB) {
this.colleagueB = colleagueB;
}
@Override
public void send(String message, SimpleColleague colleague) {
if (colleague == colleagueA) {
colleagueB.receive(message);
} else if (colleague == colleagueB) {
colleagueA.receive(message);
}
}
}
8.2.2 🔄 复杂中介者实现
// 复杂中介者:多对多交互协调
public interface ComplexMediator {
void send(String message, ComplexColleague sender);
void addColleague(ComplexColleague colleague);
void removeColleague(ComplexColleague colleague);
}
public abstract class ComplexColleague {
protected ComplexMediator mediator;
protected String name;
public ComplexColleague(String name, ComplexMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public abstract void send(String message);
public abstract void receive(String message);
public String getName() {
return name;
}
}
public class ChatUser extends ComplexColleague {
public ChatUser(String name, ComplexMediator mediator) {
super(name, mediator);
}
@Override
public void send(String message) {
System.out.println(name + " 发送消息: " + message);
mediator.send(name + ": " + message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
public class ChatRoom implements ComplexMediator {
private List<ChatUser> users = new ArrayList<>();
@Override
public void addColleague(ComplexColleague colleague) {
if (colleague instanceof ChatUser) {
users.add((ChatUser) colleague);
System.out.println(colleague.getName() + " 加入聊天室");
}
}
@Override
public void removeColleague(ComplexColleague colleague) {
if (colleague instanceof ChatUser) {
users.remove(colleague);
System.out.println(colleague.getName() + " 离开聊天室");
}
}
@Override
public void send(String message, ComplexColleague sender) {
for (ChatUser user : users) {
if (user != sender) {
user.receive(message);
}
}
}
public void broadcast(String message) {
System.out.println("系统广播: " + message);
for (ChatUser user : users) {
user.receive("系统: " + message);
}
}
}
事件中介者实现:
// 事件中介者:基于事件的松耦合
public class Event {
private String type;
private Object data;
private Object source;
public Event(String type, Object data, Object source) {
this.type = type;
this.data = data;
this.source = source;
}
public String getType() {
return type;
}
public Object getData() {
return data;
}
public Object getSource() {
return source;
}
}
public interface EventListener {
void onEvent(Event event);
}
public interface EventMediator {
void subscribe(String eventType, EventListener listener);
void unsubscribe(String eventType, EventListener listener);
void publish(Event event);
}
public class EventBus implements EventMediator {
private Map<String, List<EventListener>> listeners = new HashMap<>();
@Override
public void subscribe(String eventType, EventListener listener) {
listeners.computeIfAbsent(eventType, k -> new ArrayList<>()).add(listener);
System.out.println("订阅事件: " + eventType);
}
@Override
public void unsubscribe(String eventType, EventListener listener) {
List<EventListener> eventListeners = listeners.get(eventType);
if (eventListeners != null) {
eventListeners.remove(listener);
System.out.println("取消订阅事件: " + eventType);
}
}
@Override
public void publish(Event event) {
List<EventListener> eventListeners = listeners.get(event.getType());
if (eventListeners != null) {
for (EventListener listener : eventListeners) {
listener.onEvent(event);
}
}
}
}
public class UIComponent {
private String name;
private EventMediator mediator;
public UIComponent(String name, EventMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public void click() {
System.out.println(name + " 被点击");
Event event = new Event("click", "点击事件", this);
mediator.publish(event);
}
public void change(String value) {
System.out.println(name + " 值改变为: " + value);
Event event = new Event("change", value, this);
mediator.publish(event);
}
public String getName() {
return name;
}
}
public class Button extends UIComponent {
public Button(String name, EventMediator mediator) {
super(name, mediator);
}
}
public class TextField extends UIComponent {
public TextField(String name, EventMediator mediator) {
super(name, mediator);
}
}
public class Label extends UIComponent {
public Label(String name, EventMediator mediator) {
super(name, mediator);
}
}
public class UIEventHandler implements EventListener {
private String name;
public UIEventHandler(String name) {
this.name = name;
}
@Override
public void onEvent(Event event) {
System.out.println(name + " 处理事件: " + event.getType() +
" 数据: " + event.getData() +
" 来源: " + ((UIComponent) event.getSource()).getName());
// 根据事件类型执行不同的处理逻辑
switch (event.getType()) {
case "click":
handleClick(event);
break;
case "change":
handleChange(event);
break;
}
}
private void handleClick(Event event) {
System.out.println("处理点击事件");
}
private void handleChange(Event event) {
System.out.println("处理值改变事件");
}
}
// 使用示例
public class EventMediatorDemo {
public static void main(String[] args) {
EventBus eventBus = new EventBus();
// 创建UI组件
Button button = new Button("提交按钮", eventBus);
TextField textField = new TextField("用户名输入框", eventBus);
Label label = new Label("状态标签", eventBus);
// 创建事件处理器
UIEventHandler clickHandler = new UIEventHandler("点击处理器");
UIEventHandler changeHandler = new UIEventHandler("改变处理器");
// 订阅事件
eventBus.subscribe("click", clickHandler);
eventBus.subscribe("change", changeHandler);
// 模拟用户交互
System.out.println("=== 模拟用户交互 ===");
textField.change("张三");
button.click();
// 取消订阅
eventBus.unsubscribe("click", clickHandler);
System.out.println("\n=== 取消订阅后 ===");
button.click(); // 这次点击不会被处理
}
}
8.2.3 🎯 标准实现示例
// 中介者接口 - 定义同事间交互的方法
public interface Mediator {
void send(String message, Colleague colleague);
}
// 同事抽象类 - 需要交互的对象
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
public abstract void send(String message);
public abstract void receive(String message);
}
// 具体同事A - 实现同事A的行为
public class ConcreteColleagueA extends Colleague {
public ConcreteColleagueA(Mediator mediator) {
super(mediator);
}
@Override
public void send(String message) {
System.out.println("同事A发送消息: " + message);
mediator.send(message, this);
}
@Override
public void receive(String message) {
System.out.println("同事A收到消息: " + message);
}
}
// 具体同事B - 实现同事B的行为
public class ConcreteColleagueB extends Colleague {
public ConcreteColleagueB(Mediator mediator) {
super(mediator);
}
@Override
public void send(String message) {
System.out.println("同事B发送消息: " + message);
mediator.send(message, this);
}
@Override
public void receive(String message) {
System.out.println("同事B收到消息: " + message);
}
}
// 具体中介者 - 实现交互逻辑
public class ConcreteMediator implements Mediator {
private ConcreteColleagueA colleagueA;
private ConcreteColleagueB colleagueB;
public void setColleagueA(ConcreteColleagueA colleagueA) {
this.colleagueA = colleagueA;
}
public void setColleagueB(ConcreteColleagueB colleagueB) {
this.colleagueB = colleagueB;
}
@Override
public void send(String message, Colleague colleague) {
if (colleague == colleagueA) {
colleagueB.receive(message);
} else if (colleague == colleagueB) {
colleagueA.receive(message);
}
}
}
8.2.4 🎯 实际应用示例
// 聊天室中介者
public class ChatRoom implements Mediator {
private List<User> users = new ArrayList<>();
public void addUser(User user) {
users.add(user);
}
@Override
public void send(String message, Colleague colleague) {
for (User user : users) {
if (user != colleague) {
user.receive(message);
}
}
}
}
// 用户
public class User extends Colleague {
private String name;
public User(String name, Mediator mediator) {
super(mediator);
this.name = name;
}
@Override
public void send(String message) {
System.out.println(name + " 发送消息: " + message);
mediator.send(name + ": " + message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " 收到消息: " + message);
}
public String getName() {
return name;
}
}
👁️ 第九部分:访问者模式(Visitor Pattern)
👁️ 访问舞者的登场 👁️
┌─────────────────────────────────────┐
│ 👁️ 访问者:我是元素操作专家! │
│ │
│ 📄 文档:"我有段落和图片!" │
│ 👁️ 访问者:"我来操作它们!" │
│ 📄 文档:"我要生成HTML!" │
│ 👁️ 访问者:"继续操作它们!" │
│ │
│ 💡 核心思想:双重分发机制 │
└─────────────────────────────────────┘
🏗️ 访问者模式UML类图
⏱️ 访问者模式时序图
9.1 🎭 什么是访问者模式?
一句话理解:在不改变类的前提下,为元素添加新的操作!
定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
应用场景:编译器设计、文档处理、报表生成、数据结构操作、图形渲染
9.2 🛠️ 访问者模式的实现
9.2.1 🏗️ 基本结构
💡 小贴士:访问者模式就像医院体检,不同科室的医生对同一个病人进行不同的检查!
核心组件:
- Visitor(访问者):定义访问元素的接口
- ConcreteVisitor(具体访问者):实现访问者接口
- Element(元素):定义接受访问的接口
- ConcreteElement(具体元素):实现元素接口
9.2.2 🚀 多种实现方式
实现方式 | 特点 | 推荐度 |
---|---|---|
双重分发 | 基于运行时类型的选择 | ⭐⭐⭐⭐⭐ |
单重分发 | 基于编译时类型的选择 | ⭐⭐⭐ |
反射访问者 | 使用反射实现动态访问 | ⭐⭐⭐⭐ |
9.2.1 🔄 双重分发实现
// 双重分发:基于运行时类型的选择
public interface DocumentElement {
void accept(DocumentVisitor visitor);
}
public class Paragraph implements DocumentElement {
private String text;
public Paragraph(String text) {
this.text = text;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this); // 第一次分发:根据visitor类型
}
public String getText() {
return text;
}
}
public class Image implements DocumentElement {
private String url;
private String alt;
public Image(String url, String alt) {
this.url = url;
this.alt = alt;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this); // 第一次分发:根据visitor类型
}
public String getUrl() {
return url;
}
public String getAlt() {
return alt;
}
}
public class Table implements DocumentElement {
private List<List<String>> data;
public Table(List<List<String>> data) {
this.data = data;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this); // 第一次分发:根据visitor类型
}
public List<List<String>> getData() {
return data;
}
}
public interface DocumentVisitor {
void visit(Paragraph paragraph); // 第二次分发:根据element类型
void visit(Image image);
void visit(Table table);
}
public class HTMLVisitor implements DocumentVisitor {
private StringBuilder html = new StringBuilder();
@Override
public void visit(Paragraph paragraph) {
html.append("<p>").append(paragraph.getText()).append("</p>\n");
}
@Override
public void visit(Image image) {
html.append("<img src=\"").append(image.getUrl())
.append("\" alt=\"").append(image.getAlt()).append("\">\n");
}
@Override
public void visit(Table table) {
html.append("<table>\n");
for (List<String> row : table.getData()) {
html.append("<tr>\n");
for (String cell : row) {
html.append("<td>").append(cell).append("</td>\n");
}
html.append("</tr>\n");
}
html.append("</table>\n");
}
public String getHTML() {
return html.toString();
}
}
public class TextVisitor implements DocumentVisitor {
private StringBuilder text = new StringBuilder();
@Override
public void visit(Paragraph paragraph) {
text.append(paragraph.getText()).append("\n");
}
@Override
public void visit(Image image) {
text.append("[图片: ").append(image.getAlt()).append("]\n");
}
@Override
public void visit(Table table) {
for (List<String> row : table.getData()) {
for (String cell : row) {
text.append(cell).append("\t");
}
text.append("\n");
}
}
public String getText() {
return text.toString();
}
}
public class PDFVisitor implements DocumentVisitor {
private StringBuilder pdf = new StringBuilder();
@Override
public void visit(Paragraph paragraph) {
pdf.append("PDF段落: ").append(paragraph.getText()).append("\n");
}
@Override
public void visit(Image image) {
pdf.append("PDF图片: ").append(image.getUrl()).append("\n");
}
@Override
public void visit(Table table) {
pdf.append("PDF表格:\n");
for (List<String> row : table.getData()) {
for (String cell : row) {
pdf.append(cell).append(" | ");
}
pdf.append("\n");
}
}
public String getPDF() {
return pdf.toString();
}
}
单重分发实现:
// 单重分发:基于编译时类型的选择
public interface SingleDispatchElement {
void accept(SingleDispatchVisitor visitor);
}
public class SingleDispatchParagraph implements SingleDispatchElement {
private String text;
public SingleDispatchParagraph(String text) {
this.text = text;
}
@Override
public void accept(SingleDispatchVisitor visitor) {
visitor.visit(this);
}
public String getText() {
return text;
}
}
public class SingleDispatchImage implements SingleDispatchElement {
private String url;
public SingleDispatchImage(String url) {
this.url = url;
}
@Override
public void accept(SingleDispatchVisitor visitor) {
visitor.visit(this);
}
public String getUrl() {
return url;
}
}
public interface SingleDispatchVisitor {
void visit(SingleDispatchParagraph paragraph);
void visit(SingleDispatchImage image);
}
public class SingleDispatchHTMLVisitor implements SingleDispatchVisitor {
private StringBuilder html = new StringBuilder();
@Override
public void visit(SingleDispatchParagraph paragraph) {
html.append("<p>").append(paragraph.getText()).append("</p>\n");
}
@Override
public void visit(SingleDispatchImage image) {
html.append("<img src=\"").append(image.getUrl()).append("\">\n");
}
public String getHTML() {
return html.toString();
}
}
9.2.3 🔮 反射访问者实现
// 反射访问者:使用反射实现动态访问
public interface ReflectiveElement {
String getType();
Map<String, Object> getProperties();
}
public class ReflectiveParagraph implements ReflectiveElement {
private String text;
public ReflectiveParagraph(String text) {
this.text = text;
}
@Override
public String getType() {
return "paragraph";
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>();
props.put("text", text);
return props;
}
}
public class ReflectiveImage implements ReflectiveElement {
private String url;
private String alt;
public ReflectiveImage(String url, String alt) {
this.url = url;
this.alt = alt;
}
@Override
public String getType() {
return "image";
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>();
props.put("url", url);
props.put("alt", alt);
return props;
}
}
public class ReflectiveTable implements ReflectiveElement {
private List<List<String>> data;
public ReflectiveTable(List<List<String>> data) {
this.data = data;
}
@Override
public String getType() {
return "table";
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>();
props.put("data", data);
return props;
}
}
public class ReflectiveVisitor {
private Map<String, Consumer<Map<String, Object>>> handlers = new HashMap<>();
private StringBuilder result = new StringBuilder();
public void registerHandler(String type, Consumer<Map<String, Object>> handler) {
handlers.put(type, handler);
}
public void visit(ReflectiveElement element) {
String type = element.getType();
Map<String, Object> properties = element.getProperties();
Consumer<Map<String, Object>> handler = handlers.get(type);
if (handler != null) {
handler.accept(properties);
} else {
System.out.println("未找到处理器: " + type);
}
}
public void append(String text) {
result.append(text);
}
public String getResult() {
return result.toString();
}
}
// 使用示例
public class ReflectiveVisitorDemo {
public static void main(String[] args) {
ReflectiveVisitor visitor = new ReflectiveVisitor();
// 注册HTML处理器
visitor.registerHandler("paragraph", props -> {
String text = (String) props.get("text");
visitor.append("<p>").append(text).append("</p>\n");
});
visitor.registerHandler("image", props -> {
String url = (String) props.get("url");
String alt = (String) props.get("alt");
visitor.append("<img src=\"").append(url)
.append("\" alt=\"").append(alt).append("\">\n");
});
visitor.registerHandler("table", props -> {
@SuppressWarnings("unchecked")
List<List<String>> data = (List<List<String>>) props.get("data");
visitor.append("<table>\n");
for (List<String> row : data) {
visitor.append("<tr>\n");
for (String cell : row) {
visitor.append("<td>").append(cell).append("</td>\n");
}
visitor.append("</tr>\n");
}
visitor.append("</table>\n");
});
// 创建文档元素
List<ReflectiveElement> elements = Arrays.asList(
new ReflectiveParagraph("这是一个段落"),
new ReflectiveImage("image.jpg", "示例图片"),
new ReflectiveTable(Arrays.asList(
Arrays.asList("姓名", "年龄"),
Arrays.asList("张三", "25"),
Arrays.asList("李四", "30")
))
);
// 访问所有元素
for (ReflectiveElement element : elements) {
visitor.visit(element);
}
System.out.println("生成的HTML:");
System.out.println(visitor.getResult());
}
}
9.2.3 🎯 标准实现示例
// 元素接口 - 被访问的对象接口
public interface Element {
void accept(Visitor visitor);
}
// 具体元素A - 具体的被访问对象
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationA() {
System.out.println("元素A的操作");
}
}
// 具体元素B - 具体的被访问对象
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationB() {
System.out.println("元素B的操作");
}
}
// 访问者接口 - 定义访问操作的接口
public interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
// 具体访问者A - 具体的访问操作实现
public class ConcreteVisitorA implements Visitor {
@Override
public void visit(ConcreteElementA element) {
System.out.println("访问者A访问元素A");
element.operationA();
}
@Override
public void visit(ConcreteElementB element) {
System.out.println("访问者A访问元素B");
element.operationB();
}
}
// 具体访问者B - 具体的访问操作实现
public class ConcreteVisitorB implements Visitor {
@Override
public void visit(ConcreteElementA element) {
System.out.println("访问者B访问元素A");
element.operationA();
}
@Override
public void visit(ConcreteElementB element) {
System.out.println("访问者B访问元素B");
element.operationB();
}
}
// 对象结构 - 管理元素的集合
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void add(Element element) {
elements.add(element);
}
public void remove(Element element) {
elements.remove(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
9.2.4 🎯 实际应用示例
// 文档元素接口
public interface DocumentElement {
void accept(DocumentVisitor visitor);
}
// 段落
public class Paragraph implements DocumentElement {
private String text;
public Paragraph(String text) {
this.text = text;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this);
}
public String getText() {
return text;
}
}
// 图片
public class Image implements DocumentElement {
private String url;
private String alt;
public Image(String url, String alt) {
this.url = url;
this.alt = alt;
}
@Override
public void accept(DocumentVisitor visitor) {
visitor.visit(this);
}
public String getUrl() {
return url;
}
public String getAlt() {
return alt;
}
}
// 文档访问者接口
public interface DocumentVisitor {
void visit(Paragraph paragraph);
void visit(Image image);
}
// HTML访问者
public class HTMLVisitor implements DocumentVisitor {
private StringBuilder html = new StringBuilder();
@Override
public void visit(Paragraph paragraph) {
html.append("<p>").append(paragraph.getText()).append("</p>\n");
}
@Override
public void visit(Image image) {
html.append("<img src=\"").append(image.getUrl())
.append("\" alt=\"").append(image.getAlt()).append("\">\n");
}
public String getHTML() {
return html.toString();
}
}
// 文本访问者
public class TextVisitor implements DocumentVisitor {
private StringBuilder text = new StringBuilder();
@Override
public void visit(Paragraph paragraph) {
text.append(paragraph.getText()).append("\n");
}
@Override
public void visit(Image image) {
text.append("[图片: ").append(image.getAlt()).append("]\n");
}
public String getText() {
return text.toString();
}
}
// 文档
public class Document {
private List<DocumentElement> elements = new ArrayList<>();
public void addElement(DocumentElement element) {
elements.add(element);
}
public void accept(DocumentVisitor visitor) {
for (DocumentElement element : elements) {
element.accept(visitor);
}
}
}
💾 第十部分:备忘录模式(Memento Pattern)
💾 备忘录舞者的登场 💾
┌─────────────────────────────────────┐
│ 💾 备忘录:我是状态保存专家! │
│ │
│ 🎮 游戏:"我要保存当前状态!" │
│ 💾 备忘录:"我来保存状态!" │
│ 🎮 游戏:"我要恢复到之前状态!" │
│ 💾 备忘录:"我来恢复状态!" │
│ │
│ 💡 核心思想:状态保存恢复 │
└─────────────────────────────────────┘
🏗️ 备忘录模式UML类图
⏱️ 备忘录模式时序图
10.1 🎭 什么是备忘录模式?
一句话理解:保存对象状态,需要时可以恢复到之前的状态,就像游戏存档!
定义:在不破坏封装性的前提下,捕获并外部化一个对象的内部状态,以便在需要时可以将对象恢复到之前的状态。
核心思想:就像游戏存档,可以保存当前状态,需要时可以回滚到之前的状态。
应用场景:
- 文本编辑器的撤销功能
- 游戏存档系统
- 数据库事务回滚
- 配置管理器的状态恢复
10.2 🛠️ 备忘录模式的实现
10.2.1 🏗️ 基本结构
💡 小贴士:备忘录模式就像游戏存档,可以保存和恢复对象的状态!
核心组件:
- Memento(备忘录):存储对象状态
- Originator(发起人):创建备忘录的对象
- Caretaker(管理者):管理备忘录的对象
10.2.2 🚀 多种实现方式
实现方式 | 特点 | 推荐度 |
---|---|---|
白箱备忘录 | 备忘录内部状态可见 | ⭐⭐⭐ |
黑箱备忘录 | 备忘录内部状态隐藏 | ⭐⭐⭐⭐⭐ |
增量备忘录 | 只保存状态变化部分 | ⭐⭐⭐⭐⭐ |
10.2.1 📦 白箱备忘录实现
// 白箱备忘录:备忘录内部状态可见
public class WhiteBoxMemento {
private final String state;
public WhiteBoxMemento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
public class WhiteBoxOriginator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("状态设置为: " + state);
}
public String getState() {
return state;
}
public WhiteBoxMemento saveState() {
return new WhiteBoxMemento(state);
}
public void restoreState(WhiteBoxMemento memento) {
this.state = memento.getState(); // 直接访问备忘录状态
System.out.println("状态恢复为: " + state);
}
}
public class WhiteBoxCareTaker {
private List<WhiteBoxMemento> mementoList = new ArrayList<>();
public void addMemento(WhiteBoxMemento memento) {
mementoList.add(memento);
}
public WhiteBoxMemento getMemento(int index) {
if (index >= 0 && index < mementoList.size()) {
return mementoList.get(index);
}
return null;
}
public int getMementoCount() {
return mementoList.size();
}
}
10.2.2 🎁 黑箱备忘录实现
// 黑箱备忘录:备忘录内部状态隐藏
public interface Memento {
// 空接口,不暴露任何方法
}
public class BlackBoxOriginator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("状态设置为: " + state);
}
public String getState() {
return state;
}
public Memento saveState() {
return new BlackBoxMemento(state);
}
public void restoreState(Memento memento) {
if (memento instanceof BlackBoxMemento) {
BlackBoxMemento blackBoxMemento = (BlackBoxMemento) memento;
this.state = blackBoxMemento.getState();
System.out.println("状态恢复为: " + state);
}
}
// 内部类,外部无法直接访问
private static class BlackBoxMemento implements Memento {
private final String state;
private BlackBoxMemento(String state) {
this.state = state;
}
private String getState() {
return state;
}
}
}
public class BlackBoxCareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void addMemento(Memento memento) {
mementoList.add(memento);
}
public Memento getMemento(int index) {
if (index >= 0 && index < mementoList.size()) {
return mementoList.get(index);
}
return null;
}
public int getMementoCount() {
return mementoList.size();
}
}
10.2.3 📊 增量备忘录实现
// 增量备忘录:只保存状态变化部分
public class IncrementalMemento {
private final Map<String, Object> changes;
private final long timestamp;
public IncrementalMemento(Map<String, Object> changes) {
this.changes = new HashMap<>(changes);
this.timestamp = System.currentTimeMillis();
}
public Map<String, Object> getChanges() {
return new HashMap<>(changes);
}
public long getTimestamp() {
return timestamp;
}
}
public class IncrementalOriginator {
private Map<String, Object> state = new HashMap<>();
private List<IncrementalMemento> mementos = new ArrayList<>();
public void setProperty(String key, Object value) {
Object oldValue = state.get(key);
if (!Objects.equals(oldValue, value)) {
state.put(key, value);
System.out.println("属性 " + key + " 设置为: " + value);
// 创建增量备忘录
Map<String, Object> changes = new HashMap<>();
changes.put(key, value);
IncrementalMemento memento = new IncrementalMemento(changes);
mementos.add(memento);
}
}
public Object getProperty(String key) {
return state.get(key);
}
public Map<String, Object> getState() {
return new HashMap<>(state);
}
public void restoreToMemento(IncrementalMemento memento) {
Map<String, Object> changes = memento.getChanges();
for (Map.Entry<String, Object> entry : changes.entrySet()) {
state.put(entry.getKey(), entry.getValue());
}
System.out.println("恢复到时间戳: " + new Date(memento.getTimestamp()));
}
public void restoreToTimestamp(long timestamp) {
// 找到指定时间戳的备忘录
for (IncrementalMemento memento : mementos) {
if (memento.getTimestamp() <= timestamp) {
restoreToMemento(memento);
}
}
}
public List<IncrementalMemento> getMementos() {
return new ArrayList<>(mementos);
}
}
// 使用示例
public class IncrementalMementoDemo {
public static void main(String[] args) {
IncrementalOriginator originator = new IncrementalOriginator();
// 设置初始状态
originator.setProperty("name", "张三");
originator.setProperty("age", 25);
originator.setProperty("city", "北京");
System.out.println("\n=== 当前状态 ===");
System.out.println("姓名: " + originator.getProperty("name"));
System.out.println("年龄: " + originator.getProperty("age"));
System.out.println("城市: " + originator.getProperty("city"));
// 修改状态
originator.setProperty("age", 26);
originator.setProperty("city", "上海");
System.out.println("\n=== 修改后状态 ===");
System.out.println("姓名: " + originator.getProperty("name"));
System.out.println("年龄: " + originator.getProperty("age"));
System.out.println("城市: " + originator.getProperty("city"));
// 查看备忘录历史
System.out.println("\n=== 备忘录历史 ===");
List<IncrementalMemento> mementos = originator.getMementos();
for (int i = 0; i < mementos.size(); i++) {
IncrementalMemento memento = mementos.get(i);
System.out.println("备忘录 " + (i + 1) + ": " +
new Date(memento.getTimestamp()) + " - " +
memento.getChanges());
}
// 恢复到第一个备忘录
if (!mementos.isEmpty()) {
System.out.println("\n=== 恢复到第一个备忘录 ===");
originator.restoreToMemento(mementos.get(0));
System.out.println("姓名: " + originator.getProperty("name"));
System.out.println("年龄: " + originator.getProperty("age"));
System.out.println("城市: " + originator.getProperty("city"));
}
}
}
10.2.3 🎯 标准实现示例
// 备忘录类 - 存储状态
public class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人类 - 需要保存状态的对象
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("状态设置为: " + state);
}
public String getState() {
return state;
}
// 创建备忘录
public Memento saveState() {
return new Memento(state);
}
// 从备忘录恢复状态
public void restoreState(Memento memento) {
this.state = memento.getState();
System.out.println("状态恢复为: " + state);
}
}
// 管理者类 - 管理备忘录
public class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void addMemento(Memento memento) {
mementoList.add(memento);
}
public Memento getMemento(int index) {
if (index >= 0 && index < mementoList.size()) {
return mementoList.get(index);
}
return null;
}
public int getMementoCount() {
return mementoList.size();
}
}
10.2.4 🎯 实际应用示例
// 文本编辑器状态
public class TextEditorState {
private final String content;
private final int cursorPosition;
public TextEditorState(String content, int cursorPosition) {
this.content = content;
this.cursorPosition = cursorPosition;
}
public String getContent() {
return content;
}
public int getCursorPosition() {
return cursorPosition;
}
}
// 文本编辑器
public class TextEditor {
private String content = "";
private int cursorPosition = 0;
public void type(String text) {
content += text;
cursorPosition += text.length();
System.out.println("输入文本: " + text + ", 当前内容: " + content);
}
public void delete() {
if (content.length() > 0) {
content = content.substring(0, content.length() - 1);
cursorPosition = Math.max(0, cursorPosition - 1);
System.out.println("删除字符, 当前内容: " + content);
}
}
public void setCursor(int position) {
cursorPosition = Math.max(0, Math.min(position, content.length()));
System.out.println("光标移动到位置: " + cursorPosition);
}
// 保存状态
public TextEditorState saveState() {
return new TextEditorState(content, cursorPosition);
}
// 恢复状态
public void restoreState(TextEditorState state) {
this.content = state.getContent();
this.cursorPosition = state.getCursorPosition();
System.out.println("恢复状态 - 内容: " + content + ", 光标位置: " + cursorPosition);
}
public String getContent() {
return content;
}
public int getCursorPosition() {
return cursorPosition;
}
}
// 撤销管理器
public class UndoManager {
private Stack<TextEditorState> undoStack = new Stack<>();
private Stack<TextEditorState> redoStack = new Stack<>();
public void saveState(TextEditorState state) {
undoStack.push(state);
redoStack.clear(); // 新的操作会清空重做栈
}
public TextEditorState undo() {
if (!undoStack.isEmpty()) {
TextEditorState state = undoStack.pop();
redoStack.push(state);
return undoStack.isEmpty() ? null : undoStack.peek();
}
return null;
}
public TextEditorState redo() {
if (!redoStack.isEmpty()) {
TextEditorState state = redoStack.pop();
undoStack.push(state);
return state;
}
return null;
}
public boolean canUndo() {
return undoStack.size() > 1; // 至少要有两个状态才能撤销
}
public boolean canRedo() {
return !redoStack.isEmpty();
}
}
// 使用示例
public class MementoPatternDemo {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
UndoManager undoManager = new UndoManager();
// 初始状态
undoManager.saveState(editor.saveState());
// 输入文本
editor.type("Hello");
undoManager.saveState(editor.saveState());
editor.type(" World");
undoManager.saveState(editor.saveState());
editor.type("!");
undoManager.saveState(editor.saveState());
System.out.println("\n=== 撤销操作 ===");
// 撤销
if (undoManager.canUndo()) {
TextEditorState state = undoManager.undo();
if (state != null) {
editor.restoreState(state);
}
}
// 再撤销
if (undoManager.canUndo()) {
TextEditorState state = undoManager.undo();
if (state != null) {
editor.restoreState(state);
}
}
System.out.println("\n=== 重做操作 ===");
// 重做
if (undoManager.canRedo()) {
TextEditorState state = undoManager.redo();
if (state != null) {
editor.restoreState(state);
}
}
}
}
10.4 备忘录模式的优缺点
优点:
- ✅ 可以保存对象的历史状态
- ✅ 实现了状态的封装,外部无法直接访问
- ✅ 支持撤销和重做操作
- ✅ 符合单一职责原则
缺点:
- ❌ 如果状态数据很大,会占用大量内存
- ❌ 频繁的保存和恢复操作可能影响性能
- ❌ 管理者类需要管理大量的备忘录对象
🗣️ 第十一部分:解释器模式(Interpreter Pattern)
🗣️ 解释舞者的登场 🗣️
┌─────────────────────────────────────┐
│ 🗣️ 解释器:我是语言解释专家! │
│ │
│ 📝 表达式:"1 + 2 * 3" │
│ 🗣️ 解释器:"我来解释执行!" │
│ 📝 表达式:"x + y * z" │
│ 🗣️ 解释器:"继续解释执行!" │
│ │
│ 💡 核心思想:语法树解析执行 │
└─────────────────────────────────────┘
🏗️ 解释器模式UML类图
⏱️ 解释器模式时序图
11.1 🎭 什么是解释器模式?
一句话理解:定义语法规则,解释执行特定语言的指令!
定义:给定一种语言,定义它的语法表示,并定义一个解释器,使用该解释器来解释语言中的句子。
核心思想:就像翻译官,能够理解并执行特定语言的指令。
应用场景:
- 数学表达式计算器
- SQL解析器
- 正则表达式解析
- 配置文件解析
- 简单脚本语言解释器
11.2 🛠️ 解释器模式的实现
11.2.1 🏗️ 基本结构
💡 小贴士:解释器模式就像翻译官,将特定的语言或表达式解释为可执行的操作!
核心组件:
- AbstractExpression(抽象表达式):定义解释操作的接口
- TerminalExpression(终结表达式):实现终结符的解释
- NonterminalExpression(非终结表达式):实现非终结符的解释
- Context(上下文):包含解释器需要的全局信息
11.2.2 🚀 多种实现方式
实现方式 | 特点 | 推荐度 |
---|---|---|
递归下降 | 自顶向下的语法分析 | ⭐⭐⭐⭐⭐ |
语法树 | 构建抽象语法树 | ⭐⭐⭐⭐⭐ |
表达式求值 | 简单的表达式计算 | ⭐⭐⭐⭐ |
11.2.1 🔄 递归下降实现
// 递归下降:自顶向下的语法分析
public class RecursiveDescentParser {
private String expression;
private int position;
private char currentChar;
public RecursiveDescentParser(String expression) {
this.expression = expression.replaceAll("\\s+", "");
this.position = 0;
this.currentChar = expression.length() > 0 ? expression.charAt(0) : '\0';
}
public Expression parse() {
return parseExpression();
}
// 表达式: term (+|- term)*
private Expression parseExpression() {
Expression left = parseTerm();
while (currentChar == '+' || currentChar == '-') {
char operator = currentChar;
advance();
Expression right = parseTerm();
if (operator == '+') {
left = new AddExpression(left, right);
} else {
left = new SubtractExpression(left, right);
}
}
return left;
}
// 项: factor (*|/ factor)*
private Expression parseTerm() {
Expression left = parseFactor();
while (currentChar == '*' || currentChar == '/') {
char operator = currentChar;
advance();
Expression right = parseFactor();
if (operator == '*') {
left = new MultiplyExpression(left, right);
} else {
left = new DivideExpression(left, right);
}
}
return left;
}
// 因子: number | (expression)
private Expression parseFactor() {
if (Character.isDigit(currentChar)) {
return parseNumber();
} else if (currentChar == '(') {
advance(); // 跳过 '('
Expression result = parseExpression();
if (currentChar == ')') {
advance(); // 跳过 ')'
return result;
} else {
throw new IllegalArgumentException("期望 ')'");
}
} else {
throw new IllegalArgumentException("意外的字符: " + currentChar);
}
}
// 数字: digit+
private Expression parseNumber() {
StringBuilder number = new StringBuilder();
while (Character.isDigit(currentChar)) {
number.append(currentChar);
advance();
}
return new NumberExpression(Integer.parseInt(number.toString()));
}
private void advance() {
position++;
if (position < expression.length()) {
currentChar = expression.charAt(position);
} else {
currentChar = '\0';
}
}
}
// 表达式接口和实现类
public interface Expression {
int interpret(Context context);
}
public class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret(Context context) {
return number;
}
}
public class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
}
public class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}
public class MultiplyExpression implements Expression {
private Expression left;
private Expression right;
public MultiplyExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) * right.interpret(context);
}
}
public class DivideExpression implements Expression {
private Expression left;
private Expression right;
public DivideExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
int rightValue = right.interpret(context);
if (rightValue == 0) {
throw new ArithmeticException("除零错误");
}
return left.interpret(context) / rightValue;
}
}
11.2.2 🌳 语法树实现
// 语法树:构建抽象语法树
public abstract class ASTNode {
public abstract int evaluate(Context context);
public abstract void accept(ASTVisitor visitor);
}
public class NumberNode extends ASTNode {
private int value;
public NumberNode(int value) {
this.value = value;
}
@Override
public int evaluate(Context context) {
return value;
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public int getValue() {
return value;
}
}
public class BinaryOpNode extends ASTNode {
private String operator;
private ASTNode left;
private ASTNode right;
public BinaryOpNode(String operator, ASTNode left, ASTNode right) {
this.operator = operator;
this.left = left;
this.right = right;
}
@Override
public int evaluate(Context context) {
int leftValue = left.evaluate(context);
int rightValue = right.evaluate(context);
switch (operator) {
case "+":
return leftValue + rightValue;
case "-":
return leftValue - rightValue;
case "*":
return leftValue * rightValue;
case "/":
if (rightValue == 0) {
throw new ArithmeticException("除零错误");
}
return leftValue / rightValue;
default:
throw new IllegalArgumentException("未知操作符: " + operator);
}
}
@Override
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public String getOperator() {
return operator;
}
public ASTNode getLeft() {
return left;
}
public ASTNode getRight() {
return right;
}
}
public interface ASTVisitor {
void visit(NumberNode node);
void visit(BinaryOpNode node);
}
public class PrintVisitor implements ASTVisitor {
private StringBuilder result = new StringBuilder();
private int indent = 0;
@Override
public void visit(NumberNode node) {
result.append(" ".repeat(indent)).append("Number: ").append(node.getValue()).append("\n");
}
@Override
public void visit(BinaryOpNode node) {
result.append(" ".repeat(indent)).append("BinaryOp: ").append(node.getOperator()).append("\n");
indent++;
node.getLeft().accept(this);
node.getRight().accept(this);
indent--;
}
public String getResult() {
return result.toString();
}
}
public class ASTBuilder {
public static ASTNode buildAST(String expression) {
// 简化的AST构建器,实际应用中需要更复杂的解析逻辑
String[] tokens = expression.replaceAll("\\s+", "").split("");
if (tokens.length == 1) {
return new NumberNode(Integer.parseInt(tokens[0]));
}
if (tokens.length == 3) {
ASTNode left = new NumberNode(Integer.parseInt(tokens[0]));
ASTNode right = new NumberNode(Integer.parseInt(tokens[2]));
return new BinaryOpNode(tokens[1], left, right);
}
// 处理更复杂的表达式
return buildComplexAST(expression);
}
private static ASTNode buildComplexAST(String expression) {
// 这里实现更复杂的AST构建逻辑
// 为了简化,我们使用递归下降解析器
RecursiveDescentParser parser = new RecursiveDescentParser(expression);
Expression exp = parser.parse();
return convertToAST(exp);
}
private static ASTNode convertToAST(Expression exp) {
if (exp instanceof NumberExpression) {
return new NumberNode(((NumberExpression) exp).interpret(new Context()));
} else if (exp instanceof AddExpression) {
AddExpression addExp = (AddExpression) exp;
return new BinaryOpNode("+",
convertToAST(addExp.getLeft()),
convertToAST(addExp.getRight()));
} else if (exp instanceof SubtractExpression) {
SubtractExpression subExp = (SubtractExpression) exp;
return new BinaryOpNode("-",
convertToAST(subExp.getLeft()),
convertToAST(subExp.getRight()));
} else if (exp instanceof MultiplyExpression) {
MultiplyExpression mulExp = (MultiplyExpression) exp;
return new BinaryOpNode("*",
convertToAST(mulExp.getLeft()),
convertToAST(mulExp.getRight()));
} else if (exp instanceof DivideExpression) {
DivideExpression divExp = (DivideExpression) exp;
return new BinaryOpNode("/",
convertToAST(divExp.getLeft()),
convertToAST(divExp.getRight()));
}
throw new IllegalArgumentException("不支持的表达式类型");
}
}
11.2.3 🧮 表达式求值实现
// 表达式求值:简单的表达式计算
public class SimpleExpressionEvaluator {
private Map<String, Integer> variables = new HashMap<>();
public void setVariable(String name, int value) {
variables.put(name, value);
}
public int evaluate(String expression) {
return evaluateExpression(expression.replaceAll("\\s+", ""));
}
private int evaluateExpression(String expr) {
if (expr.isEmpty()) {
return 0;
}
// 处理括号
if (expr.startsWith("(") && expr.endsWith(")")) {
return evaluateExpression(expr.substring(1, expr.length() - 1));
}
// 处理加法
int addIndex = findOperator(expr, '+');
if (addIndex != -1) {
return evaluateExpression(expr.substring(0, addIndex)) +
evaluateExpression(expr.substring(addIndex + 1));
}
// 处理减法
int subIndex = findOperator(expr, '-');
if (subIndex != -1) {
return evaluateExpression(expr.substring(0, subIndex)) -
evaluateExpression(expr.substring(subIndex + 1));
}
// 处理乘法
int mulIndex = findOperator(expr, '*');
if (mulIndex != -1) {
return evaluateExpression(expr.substring(0, mulIndex)) *
evaluateExpression(expr.substring(mulIndex + 1));
}
// 处理除法
int divIndex = findOperator(expr, '/');
if (divIndex != -1) {
int left = evaluateExpression(expr.substring(0, divIndex));
int right = evaluateExpression(expr.substring(divIndex + 1));
if (right == 0) {
throw new ArithmeticException("除零错误");
}
return left / right;
}
// 处理数字或变量
return parseNumberOrVariable(expr);
}
private int findOperator(String expr, char operator) {
int parenCount = 0;
for (int i = 0; i < expr.length(); i++) {
char c = expr.charAt(i);
if (c == '(') parenCount++;
else if (c == ')') parenCount--;
else if (c == operator && parenCount == 0) {
return i;
}
}
return -1;
}
private int parseNumberOrVariable(String expr) {
if (Character.isDigit(expr.charAt(0))) {
return Integer.parseInt(expr);
} else {
return variables.getOrDefault(expr, 0);
}
}
}
// 使用示例
public class ExpressionEvaluatorDemo {
public static void main(String[] args) {
SimpleExpressionEvaluator evaluator = new SimpleExpressionEvaluator();
// 设置变量
evaluator.setVariable("x", 10);
evaluator.setVariable("y", 5);
// 测试简单表达式
System.out.println("2 + 3 = " + evaluator.evaluate("2 + 3"));
System.out.println("10 - 5 = " + evaluator.evaluate("10 - 5"));
System.out.println("4 * 6 = " + evaluator.evaluate("4 * 6"));
System.out.println("15 / 3 = " + evaluator.evaluate("15 / 3"));
// 测试复杂表达式
System.out.println("(2 + 3) * 4 = " + evaluator.evaluate("(2 + 3) * 4"));
System.out.println("x + y = " + evaluator.evaluate("x + y"));
System.out.println("x * y - 10 = " + evaluator.evaluate("x * y - 10"));
// 测试带括号的表达式
System.out.println("(x + y) * 2 = " + evaluator.evaluate("(x + y) * 2"));
}
}
11.2.3 🎯 标准实现示例
// 抽象表达式 - 定义解释操作的接口
public interface Expression {
int interpret(Context context);
}
// 上下文类 - 包含解释器需要的全局信息
public class Context {
private Map<String, Integer> variables = new HashMap<>();
public void setVariable(String name, int value) {
variables.put(name, value);
}
public int getVariable(String name) {
return variables.getOrDefault(name, 0);
}
}
// 终结符表达式 - 数字
public class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret(Context context) {
return number;
}
}
// 终结符表达式 - 变量
public class VariableExpression implements Expression {
private String variable;
public VariableExpression(String variable) {
this.variable = variable;
}
@Override
public int interpret(Context context) {
return context.getVariable(variable);
}
}
// 非终结符表达式 - 加法
public class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
}
// 非终结符表达式 - 减法
public class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}
// 非终结符表达式 - 乘法
public class MultiplyExpression implements Expression {
private Expression left;
private Expression right;
public MultiplyExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) * right.interpret(context);
}
}
11.2.4 🎯 实际应用示例
// 表达式解析器
public class ExpressionParser {
public static Expression parse(String expression) {
// 简单的解析逻辑,实际应用中可能需要更复杂的解析器
expression = expression.replaceAll("\\s+", ""); // 移除空格
if (expression.contains("+")) {
String[] parts = expression.split("\\+", 2);
return new AddExpression(parse(parts[0]), parse(parts[1]));
} else if (expression.contains("-")) {
String[] parts = expression.split("-", 2);
return new SubtractExpression(parse(parts[0]), parse(parts[1]));
} else if (expression.contains("*")) {
String[] parts = expression.split("\\*", 2);
return new MultiplyExpression(parse(parts[0]), parse(parts[1]));
} else if (expression.matches("\\d+")) {
return new NumberExpression(Integer.parseInt(expression));
} else if (expression.matches("[a-zA-Z]+")) {
return new VariableExpression(expression);
} else {
throw new IllegalArgumentException("无法解析表达式: " + expression);
}
}
}
// 计算器
public class Calculator {
private Context context = new Context();
public void setVariable(String name, int value) {
context.setVariable(name, value);
}
public int calculate(String expression) {
Expression exp = ExpressionParser.parse(expression);
return exp.interpret(context);
}
}
// 使用示例
public class InterpreterPatternDemo {
public static void main(String[] args) {
Calculator calculator = new Calculator();
// 设置变量
calculator.setVariable("x", 10);
calculator.setVariable("y", 5);
// 计算表达式
System.out.println("x + y = " + calculator.calculate("x + y")); // 15
System.out.println("x - y = " + calculator.calculate("x - y")); // 5
System.out.println("x * y = " + calculator.calculate("x * y")); // 50
System.out.println("10 + 20 = " + calculator.calculate("10 + 20")); // 30
System.out.println("x + 5 = " + calculator.calculate("x + 5")); // 15
}
}
11.3.3 更复杂的表达式解析器
// 支持括号的表达式解析器
public class AdvancedExpressionParser {
private String expression;
private int position;
public Expression parse(String expression) {
this.expression = expression.replaceAll("\\s+", "");
this.position = 0;
return parseExpression();
}
private Expression parseExpression() {
Expression left = parseTerm();
while (position < expression.length() &&
(expression.charAt(position) == '+' || expression.charAt(position) == '-')) {
char operator = expression.charAt(position++);
Expression right = parseTerm();
if (operator == '+') {
left = new AddExpression(left, right);
} else {
left = new SubtractExpression(left, right);
}
}
return left;
}
private Expression parseTerm() {
Expression left = parseFactor();
while (position < expression.length() && expression.charAt(position) == '*') {
position++; // 跳过 *
Expression right = parseFactor();
left = new MultiplyExpression(left, right);
}
return left;
}
private Expression parseFactor() {
char current = expression.charAt(position);
if (current == '(') {
position++; // 跳过 (
Expression result = parseExpression();
position++; // 跳过 )
return result;
} else if (Character.isDigit(current)) {
return parseNumber();
} else if (Character.isLetter(current)) {
return parseVariable();
} else {
throw new IllegalArgumentException("意外的字符: " + current);
}
}
private Expression parseNumber() {
StringBuilder number = new StringBuilder();
while (position < expression.length() && Character.isDigit(expression.charAt(position))) {
number.append(expression.charAt(position++));
}
return new NumberExpression(Integer.parseInt(number.toString()));
}
private Expression parseVariable() {
StringBuilder variable = new StringBuilder();
while (position < expression.length() && Character.isLetter(expression.charAt(position))) {
variable.append(expression.charAt(position++));
}
return new VariableExpression(variable.toString());
}
}
// 使用高级解析器
public class AdvancedCalculator {
private Context context = new Context();
private AdvancedExpressionParser parser = new AdvancedExpressionParser();
public void setVariable(String name, int value) {
context.setVariable(name, value);
}
public int calculate(String expression) {
Expression exp = parser.parse(expression);
return exp.interpret(context);
}
}
// 测试高级计算器
public class AdvancedInterpreterDemo {
public static void main(String[] args) {
AdvancedCalculator calculator = new AdvancedCalculator();
calculator.setVariable("x", 10);
calculator.setVariable("y", 5);
calculator.setVariable("z", 2);
// 测试复杂表达式
System.out.println("(x + y) * z = " + calculator.calculate("(x + y) * z")); // 30
System.out.println("x + y * z = " + calculator.calculate("x + y * z")); // 20
System.out.println("(10 + 5) * 3 = " + calculator.calculate("(10 + 5) * 3")); // 45
}
}
11.4 解释器模式的优缺点
优点:
- ✅ 易于扩展语法规则
- ✅ 每个语法规则都是一个类,便于维护
- ✅ 可以方便地添加新的解释操作
- ✅ 符合开闭原则
缺点:
- ❌ 对于复杂语法,会产生大量的类
- ❌ 解析效率相对较低
- ❌ 不适合复杂的语言解析
- ❌ 可能导致类层次结构复杂
11.5 解释器模式在JDK中的应用
// Java正则表达式使用了解释器模式
public class RegexExample {
public static void main(String[] args) {
String text = "Hello World 123";
// Pattern.compile() 使用了解释器模式来解析正则表达式
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println("找到数字: " + matcher.group());
}
}
}
🎉 总结:行为型设计模式的舞蹈盛宴
🎭 行为型设计模式总结 🎭
┌─────────────────────────────────────┐
│ 🕺 十一位舞者的精彩表演回顾! │
│ │
│ 👀 观察者:一对多通知的优雅舞者 │
│ 🎯 策略者:算法选择的灵活舞者 │
│ 📝 命令者:请求封装的智慧舞者 │
│ 🔄 状态者:状态变化的艺术舞者 │
│ 📋 模板者:算法框架的设计舞者 │
│ 🔍 迭代者:集合遍历的精准舞者 │
│ ⛓️ 责任链:请求处理的链式舞者 │
│ 🤝 中介者:对象交互的协调舞者 │
│ 👁️ 访问者:元素操作的专家舞者 │
│ 💾 备忘录:状态保存的记忆舞者 │
│ 🗣️ 解释器:语言解释的翻译舞者 │
│ │
│ 🎊 感谢观看这场精彩的舞蹈表演! │
└─────────────────────────────────────┘
🎯 各模式的特点与选择指南
模式 | 核心特点 | 适用场景 | 推荐度 |
---|---|---|---|
👀 观察者模式 | 一对多通知机制,松耦合通信 | 事件处理、消息推送、数据绑定、GUI事件 | ⭐⭐⭐⭐⭐ |
🎯 策略模式 | 算法封装,运行时切换 | 支付方式、排序算法、游戏技能、压缩算法 | ⭐⭐⭐⭐⭐ |
📝 命令模式 | 请求封装,支持撤销重做 | 遥控器、撤销重做、宏命令、日志记录 | ⭐⭐⭐⭐⭐ |
🔄 状态模式 | 状态封装,行为随状态变化 | 状态机、游戏角色、订单状态、工作流 | ⭐⭐⭐⭐ |
📋 模板方法模式 | 算法骨架固定,步骤可变 | 算法框架、代码复用、流程控制、钩子方法 | ⭐⭐⭐⭐ |
🔍 迭代器模式 | 统一遍历接口,封装内部结构 | 集合遍历、分页查询、数据结构访问 | ⭐⭐⭐⭐ |
⛓️ 责任链模式 | 请求沿链传递,动态组合处理 | 请求处理、审批流程、异常处理、过滤器 | ⭐⭐⭐⭐ |
🤝 中介者模式 | 集中控制交互,降低对象耦合 | 聊天系统、事件总线、GUI交互、服务注册 | ⭐⭐⭐ |
👁️ 访问者模式 | 双重分发,不改变类定义新操作 | 编译器、文档处理、报表生成、数据结构操作 | ⭐⭐⭐ |
💾 备忘录模式 | 状态保存恢复,历史记录管理 | 撤销功能、游戏存档、状态恢复、配置管理 | ⭐⭐⭐ |
🗣️ 解释器模式 | 语法树解析,递归解释执行 | 表达式计算、SQL解析、脚本解释、配置文件 | ⭐⭐⭐ |
🚀 选择建议:何时使用哪种模式?
🎯 按问题类型选择
1. 对象间通信问题
- 观察者模式:一对多通知场景
- 中介者模式:复杂对象交互场景
- 命令模式:请求封装和参数化场景
2. 算法选择问题
- 策略模式:多种算法可替换场景
- 模板方法模式:算法框架固定场景
- 解释器模式:语言解析场景
3. 状态管理问题
- 状态模式:状态影响行为场景
- 备忘录模式:状态保存恢复场景
4. 集合访问问题
- 迭代器模式:统一遍历接口场景
- 访问者模式:对元素执行不同操作场景
5. 请求处理问题
- 责任链模式:请求沿链传递场景
- 命令模式:请求封装和队列场景
🎯 按应用场景选择
应用场景 | 推荐模式 | 原因 |
---|---|---|
GUI事件处理 | 观察者模式 | 事件驱动,松耦合 |
支付系统 | 策略模式 | 多种支付方式,易于扩展 |
文本编辑器 | 命令模式 | 支持撤销重做 |
游戏状态管理 | 状态模式 | 角色状态影响行为 |
数据处理框架 | 模板方法模式 | 算法骨架固定,步骤可变 |
集合遍历 | 迭代器模式 | 统一访问接口 |
审批流程 | 责任链模式 | 请求沿审批链传递 |
聊天系统 | 中介者模式 | 用户间交互协调 |
编译器 | 访问者模式 | 对语法树执行不同操作 |
游戏存档 | 备忘录模式 | 保存和恢复游戏状态 |
表达式计算 | 解释器模式 | 解析和执行表达式 |
💡 实践要点与最佳实践
🎯 选择策略
- 理解场景:根据具体需求选择合适的设计模式
- 避免过度设计:不是所有地方都需要使用设计模式
- 考虑性能:设计模式可能带来一定的性能开销
- 保持简单:优先选择简单的解决方案
- 遵循SOLID原则:确保设计模式的使用符合设计原则
🚀 实战建议
- 从简单开始:先尝试最简单的解决方案
- 渐进式重构:在需要时逐步引入设计模式
- 团队协作:确保团队成员都理解设计模式的使用
- 文档记录:记录设计模式的使用原因和效果
- 接口优先:定义清晰的接口,提高灵活性
- 组合优于继承:使用组合实现,避免继承的局限性
⚠️ 常见陷阱与注意事项
- 过度使用:不要为了使用模式而使用模式
- 性能问题:某些模式可能带来性能开销
- 复杂性增加:模式可能增加代码复杂性
- 学习成本:团队成员需要理解模式的使用
- 维护困难:过度使用模式可能导致维护困难
🌟 结语
通过深入理解这十一种行为型设计模式,我们掌握了"对象协作的舞蹈艺术":
- 观察者模式教会我们如何实现优雅的一对多通知机制
- 策略模式让我们学会封装算法,实现运行时切换
- 命令模式帮助我们封装请求,支持撤销重做操作
- 状态模式让我们学会根据状态改变对象行为
- 模板方法模式教会我们如何定义算法骨架,让子类实现具体步骤
- 迭代器模式让我们学会统一访问集合元素的方式
- 责任链模式帮助我们构建灵活的处理链
- 中介者模式让我们学会集中管理对象间的交互
- 访问者模式教会我们如何在不改变类的情况下添加新操作
- 备忘录模式帮助我们保存和恢复对象状态
- 解释器模式让我们学会解析和执行特定语言的指令
记住,设计模式不是银弹,而是工具箱中的利器。在实际项目中,要根据具体需求灵活运用,让对象间的协作既优雅又高效!
让我们一起在代码的舞台上,跳出优雅的舞蹈! 💃🕺
🎭 延伸阅读:
🚀 实践建议:建议在实际项目中尝试使用这些模式,从简单的场景开始,逐步掌握它们的精髓!记住,最好的学习方式就是动手实践!