11.30 实验十九中介者模式 实验二十备忘录模式

实验19:中介者模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解中介者模式的动机,掌握该模式的结构;
2、能够利用中介者模式解决实际问题。

[实验任务一]:虚拟聊天室
在“虚拟聊天室”实例中增加一个新的具体聊天室类和一个新的具体会员类,要求如下:

  1. 新的具体聊天室中发送的图片大小不得超过20M。
  2. 新的具体聊天室中发送的文字长度不得超过100个字符。
  3. 新的具体会员类可以发送图片信息和文本信息。
  4. 新的具体会员类在发送文本信息时,可以在信息后加上时间。
    修改客户端测试类,注意原有系统类代码和客户端代码的修改。
    实验要求:
    1.画出对应的类图;
    2.提交源代码;
  5. 注意编程规范。
    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. 注意编程规范。
image

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();
    }}
posted @ 2026-01-03 13:34  liu某人  阅读(5)  评论(0)    收藏  举报