11.30 实验十九中介者模式 实验二十备忘录模式
实验19:中介者模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解中介者模式的动机,掌握该模式的结构;
2、能够利用中介者模式解决实际问题。
[实验任务一]:虚拟聊天室
在“虚拟聊天室”实例中增加一个新的具体聊天室类和一个新的具体会员类,要求如下:
- 新的具体聊天室中发送的图片大小不得超过20M。
- 新的具体聊天室中发送的文字长度不得超过100个字符。
- 新的具体会员类可以发送图片信息和文本信息。
- 新的具体会员类在发送文本信息时,可以在信息后加上时间。
修改客户端测试类,注意原有系统类代码和客户端代码的修改。
实验要求:
1.画出对应的类图;
2.提交源代码; - 注意编程规范。
![image]()
ChatroomMediator.java
/public interface ChatroomMediator {
/**
* 转发文本消息
* @param sender 发送者
* @param text 文本内容
*/
void sendText(Member sender, String text);
/**
* 转发图片消息
* @param sender 发送者
* @param imageName 图片名称
* @param size 图片大小(字节)
*/
void sendImage(Member sender, String imageName, long size);}
CommonChatroom.java
public class CommonChatroom implements ChatroomMediator {
@Override
public void sendText(Member sender, String text) {
System.out.println("【普通聊天室】" + sender.getName() + "发送文本:" + text);
}
@Override
public void sendImage(Member sender, String imageName, long size) {
System.out.println("【普通聊天室】" + sender.getName() + "发送图片:" + imageName + "(大小:" + size + "字节)");
}}
RestrictedChatroom.java
public class RestrictedChatroom implements ChatroomMediator {
// 文本最大长度:100字符
private static final int MAX_TEXT_LENGTH = 100;
// 图片最大大小:20M = 20 * 1024 * 1024 = 20971520字节
private static final long MAX_IMAGE_SIZE = 20 * 1024 * 1024L;
@Override
public void sendText(Member sender, String text) {
if (text.length() > MAX_TEXT_LENGTH) {
System.out.println("【受限聊天室】" + sender.getName() + "发送文本失败:长度超过" + MAX_TEXT_LENGTH + "字符(当前:" + text.length() + ")");
return;
}
System.out.println("【受限聊天室】" + sender.getName() + "发送文本:" + text);
}
@Override
public void sendImage(Member sender, String imageName, long size) {
if (size > MAX_IMAGE_SIZE) {
System.out.println("【受限聊天室】" + sender.getName() + "发送图片失败:大小超过20M(当前:" + size / 1024 / 1024 + "M)");
return;
}
System.out.println("【受限聊天室】" + sender.getName() + "发送图片:" + imageName + "(大小:" + size / 1024 / 1024 + "M)");
}}
Member.java
public abstract class Member {
// 会员姓名
protected String name;
// 关联的聊天室中介者
protected ChatroomMediator mediator;
/**
* 构造方法:初始化姓名
* @param name 会员姓名
*/
public Member(String name) {
this.name = name;
}
/**
* 设置聊天室中介者
* @param mediator 聊天室实例
*/
public void setMediator(ChatroomMediator mediator) {
this.mediator = mediator;
}
/**
* 获取会员姓名
* @return 姓名
*/
public String getName() {
return name;
}
// 抽象方法:发送文本(子类实现)
public abstract void sendText(String text);
// 抽象方法:发送图片(子类实现)
public abstract void sendImage(String imageName, long size);}
CommonMember.java
public class CommonMember extends Member {
public CommonMember(String name) {
super(name);
}
@Override
public void sendText(String text) {
if (mediator != null) {
mediator.sendText(this, text);
} else {
System.out.println("错误:未关联聊天室!");
}
}
@Override
public void sendImage(String imageName, long size) {
if (mediator != null) {
mediator.sendImage(this, imageName, size);
} else {
System.out.println("错误:未关联聊天室!");
}
}}
AdvancedMember.java
public class AdvancedMember extends Member {
// 时间格式化器
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public AdvancedMember(String name) {
super(name);
}
@Override
public void sendText(String text) {
if (mediator != null) {
// 追加当前时间戳
String textWithTime = text + "【发送时间:" + LocalDateTime.now().format(TIME_FORMATTER) + "】";
mediator.sendText(this, textWithTime);
} else {
System.out.println("错误:未关联聊天室!");
}
}
@Override
public void sendImage(String imageName, long size) {
if (mediator != null) {
mediator.sendImage(this, imageName, size);
} else {
System.out.println("错误:未关联聊天室!");
}
}}
ChatroomTest.java
/public class ChatroomTest {
public static void main(String[] args) {
// 1. 创建聊天室中介者
ChatroomMediator commonChatroom = new CommonChatroom();
ChatroomMediator restrictedChatroom = new RestrictedChatroom();
// 2. 创建会员
Member commonUser = new CommonMember("普通用户A");
Member advancedUser = new AdvancedMember("高级用户B");
// 3. 普通会员加入普通聊天室
System.out.println("===== 普通聊天室测试 =====");
commonUser.setMediator(commonChatroom);
commonUser.sendText("大家好!这是普通会员的消息");
commonUser.sendImage("风景.jpg", 5 * 1024 * 1024); // 5M图片
// 4. 高级会员加入受限聊天室
System.out.println("\n===== 受限聊天室测试 =====");
advancedUser.setMediator(restrictedChatroom);
// 测试合法文本(带时间戳)
advancedUser.sendText("受限聊天室的合法消息,长度小于100字符");
// 测试超长文本
advancedUser.sendText("这是一条超长的测试文本,目的是验证受限聊天室的文本长度限制,当前字符数明显超过100个,看看是否会被拦截");
// 测试合法图片(10M)
advancedUser.sendImage("头像.png", 10 * 1024 * 1024);
// 测试超大图片(25M)
advancedUser.sendImage("视频截图.png", 25 * 1024 * 1024);
// 5. 普通会员加入受限聊天室
System.out.println("\n===== 普通会员在受限聊天室测试 =====");
commonUser.setMediator(restrictedChatroom);
commonUser.sendText("普通会员在受限聊天室的消息");
commonUser.sendImage("文件.png", 21 * 1024 * 1024); // 21M图片(超限)
}}
实验 20:备忘录模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解备忘录模式的动机,掌握该模式的结构;
2、能够利用备忘录模式解决实际问题。
[实验任务一]:多次撤销
改进课堂上的“用户信息操作撤销”实例,使得系统可以实现多次撤销(可以使用HashMap、ArrayList等集合数据结构实现)。
实验要求:
1.画出对应的类图;
2.提交源代码;
3. 注意编程规范。

UserMemento.java
public class UserMemento {
// 保存的用户状态(与原发器一致)
private final String name;
private final int age;
private final String phone;
/**
* 构造方法:初始化备忘录状态(仅原发器可调用)
* @param name 姓名
* @param age 年龄
* @param phone 手机号
*/
public UserMemento(String name, int age, String phone) {
this.name = name;
this.age = age;
this.phone = phone;
}
// 只读getter方法,供原发器恢复状态
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}}
UserInfo.java
public class UserInfo {
// 用户状态属性
private String name;
private int age;
private String phone;
/**
* 构造方法:初始化用户信息
* @param name 姓名
* @param age 年龄
* @param phone 手机号
*/
public UserInfo(String name, int age, String phone) {
this.name = name;
this.age = age;
this.phone = phone;
}
/**
* 创建备忘录:保存当前状态
* @return 包含当前状态的备忘录
*/
public UserMemento createMemento() {
return new UserMemento(name, age, phone);
}
/**
* 恢复备忘录:从备忘录中回滚状态
* @param memento 要恢复的备忘录
*/
public void restoreMemento(UserMemento memento) {
this.name = memento.getName();
this.age = memento.getAge();
this.phone = memento.getPhone();
}
// 属性修改方法(每次修改前需保存当前状态到管理者)
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setPhone(String phone) {
this.phone = phone;
}
/**
* 显示当前用户状态
*/
public void show() {
System.out.println("当前用户信息:姓名=" + name + ",年龄=" + age + ",手机号=" + phone);
}}
Caretaker.java
import java.util.ArrayList;import java.util.List;
public class Caretaker {
// 存储备忘录的列表(按操作顺序保存)
private final List<UserMemento> mementos = new ArrayList<>();
// 当前状态索引(指向最新备忘录的下一个位置)
private int currentIndex = 0;
/**
* 保存备忘录到列表
* @param memento 要保存的备忘录
*/
public void saveMemento(UserMemento memento) {
// 如果是中间撤销后新增操作,清除后续的备忘录(避免redo冲突)
if (currentIndex < mementos.size()) {
mementos.subList(currentIndex, mementos.size()).clear();
}
mementos.add(memento);
currentIndex++;
}
/**
* 撤销操作:获取上一个备忘录
* @return 上一个状态的备忘录,无则返回null
*/
public UserMemento undo() {
if (canUndo()) {
currentIndex--;
return mementos.get(currentIndex - 1); // 索引-1为上一个状态
}
System.out.println("⚠️ 无历史状态可撤销!");
return null;
}
/**
* 判断是否可撤销
* @return true=可撤销,false=不可撤销
*/
public boolean canUndo() {
return currentIndex > 1; // 至少有一个历史状态(初始状态为索引0)
}}
MementoTest.java
public class MementoTest {
public static void main(String[] args) {
// 1. 初始化原发器(用户信息)和管理者
UserInfo user = new UserInfo("张三", 20, "13800138000");
Caretaker caretaker = new Caretaker();
// 2. 保存初始状态(首次操作前必须保存)
caretaker.saveMemento(user.createMemento());
System.out.println("===== 初始状态 =====");
user.show();
// 3. 修改状态1:更新姓名和年龄
user.setName("李四");
user.setAge(22);
caretaker.saveMemento(user.createMemento());
System.out.println("\n===== 修改状态1 =====");
user.show();
// 4. 修改状态2:更新手机号
user.setPhone("13900139000");
caretaker.saveMemento(user.createMemento());
System.out.println("\n===== 修改状态2 =====");
user.show();
// 5. 修改状态3:更新年龄
user.setAge(25);
caretaker.saveMemento(user.createMemento());
System.out.println("\n===== 修改状态3 =====");
user.show();
// 6. 第一次撤销:回到状态2
System.out.println("\n===== 第一次撤销 =====");
if (caretaker.canUndo()) {
user.restoreMemento(caretaker.undo());
user.show();
}
// 7. 第二次撤销:回到状态1
System.out.println("\n===== 第二次撤销 =====");
if (caretaker.canUndo()) {
user.restoreMemento(caretaker.undo());
user.show();
}
// 8. 第三次撤销:回到初始状态
System.out.println("\n===== 第三次撤销 =====");
if (caretaker.canUndo()) {
user.restoreMemento(caretaker.undo());
user.show();
}
// 9. 第四次撤销:无历史状态
System.out.println("\n===== 第四次撤销 =====");
caretaker.undo();
}}


浙公网安备 33010602011771号