Java设计模式之行为型-备忘录模式(UML类图+案例分析)

news2024/10/6 18:25:24

目录

一、基础概念

二、UML类图

三、角色设计

四、案例分析

五、总结 


一、基础概念

备忘录模式是一种行为型设计模式,它允许保存一个对象的内部状态到一个备忘录对象中,这样就可以在需要的时候恢复这个对象的状态了,同时又不违反封装性原则。

这个模式的核心就是备忘录对象,它负责存储目标对象的内部状态信息,并且可以通过方法访问这些状态数据。而目标对象负责创建备忘录对象,并在备忘录对象中保存自身状态。管理者角色负责存储和恢复备忘录对象,但是不能直接看到或者修改备忘录对象中的状态数据。 

二、UML类图

三、角色设计

角色描述
发起人角色负责创建一个备忘录,记录自身需要保存的状态,具备回滚的功能
备忘录角色用于存储发起人角色的内部状态,而且可以防止发起人角色以外的对象访问权限
管理者角色负责存储、提供管理备忘录角色,不可以修改备忘录角色的内容

四、案例分析

在我们日常开发中,必备的版本控制工具就是Git,可以提交版本,回滚到指定版本,下面我们就通过备忘录设计模式来实现一个简单的版本控制功能,代码如下:

它扮演备忘录角色,用于存储某个时刻的状态快照。它有两个成员变量version和content,分别记录版本号和内容:

public class Commit {

    private String version;
    private String content;

    public Commit(String version, String content) {
        this.version = version;
        this.content = content;
    }

    public String getVersion() {
        return version;
    }

    public String getContent() {
        return content;
    }

}

Repository类是发起人角色,它管理具体的内容。该类有一个成员变量content记录内容,以及setContent和getContent方法用于设置和获取内容。另外还有一个commit方法可以保存一个状态快照,和一个rollback方法可以从快照恢复状态。

public class Repository {

    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Commit commit(String version) {
        return new Commit(version, content);
    }

    public void rollback(Commit commit) {
        content = commit.getContent();
    }

}

Git类在这里是管理者角色,它持有一个Commit对象列表来记录每次提交的备忘录。该类提供了commit和rollback两种方法,commit是保存新提交的备忘录,rollback可以回滚到指定版本。

import java.util.ArrayList;
import java.util.List;

public class Git {

    private List<Commit> commits = new ArrayList<>();

    public void commit(Repository repo, String version) {
        commits.add(repo.commit(version));
    }

    public void rollback(Repository repo, String version) {
        for(Commit commit : commits) {
            if(commit.getVersion().equals(version)) {
                repo.rollback(commit);
                break;
            }
        }
    }
}

模拟一个客户端,演示了这个存储库的基本用法。首先创建Repository和Git对象,然后新增几个版本到存储库,最后回滚到第一个版本,在关键点会打印输出内容,以展示执行流程。 

public class Client {

    public static void main(String[] args) {
        Repository repository = new Repository();
        Git git = new Git();

        repository.setContent("version 1");
        git.commit(repository, "version 1");

        repository.setContent("version 2");
        git.commit(repository, "version 2");

        repository.setContent("version 3");
        git.commit(repository, "version 3");

        git.rollback(repository, "version 1");
        System.out.println(repository.getContent());
    }
}

运行结果如下: 

整体上这个例子使用了备忘录模式的三个主要角色,将状态存入备忘录对象,发起人负责状态的管理和保存,管理者保存备忘录的历史,从而实现了版本控制和回滚的功能。这就是一个使用备忘录模式实现简单Git版本控制的设计和执行过程。 

五、总结 

优点:

1、提供了保持对象内部状态历史的能力,可以方便地将对象恢复到历史某个状态。

2、实现了内部状态的封装,除了创建它的发起人之外,其他对象都不能访问这些状态信息。

3、简化了发起人类,发起人不需要管理和保存其内部状态的各个历史版本,所有状态历史由管理者完成。

缺点:

1、资源消耗大,如果要保存的历史状态很多,会占用较多内存资源。

2、破坏了对象的封装性,其他对象可以通过管理者访问发起人的内部状态。

3、复杂度较高,需要维护发起人、备忘录、管理者三个角色对象。

应用场景:

1、需要保存对象在某个时刻的状态快照,比如实现撤销操作。

2、需要对对象的状态历史保持跟踪,如游戏进度保存。

3、当对象的状态变化复杂时,可以使用备忘录模式保持对象内部状态的一致性。

4、当直接访问封装的对象需要暴露对象实现细节时,可以通过备忘录间接访问对象状态。

符合的设计原则:

1、开闭原则(Open Close Principle)

开闭原则要求软件实体应对扩展开放,对修改关闭。备忘录模式通过创建新的备忘录类来保存和恢复对象状态,扩展了现有类的功能,而无需修改这些类的代码。符合了对扩展开放的要求。

2封装原则(Encapsulation Principle)

封装原则要求隐藏实现细节,只通过公共接口提供访问。在备忘录模式中,备忘录类封装了对象状态,外部只能通过备忘录的限定接口访问,不能直接操作对象的内部状态,提高了封装性。

3单一职责原则(Single Responsibility Principle)

单一职责原则要求一个类只有一个引起它变化的原因。备忘录模式中,原发器类负责业务逻辑,备忘录类负责存储状态,管理者类负责备忘录的管理,每一个类都只有单一职责。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/751793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.5 纹理

这次笔记时间有点久&#xff0c;主要是这节课讲的东西需要很多基础来铺垫&#xff0c;看完了后感觉缺失信息很多&#xff0c;又去补了GAMES 101 3~10节内容。 强烈建议看不懂的先去学习GMAES101 网址Lecture 08 Shading 2 (Shading, Pipeline and Texture Mapping)_哔哩哔哩_bi…

你知道哪些Linux 发行版采用 了KDE Plasma 吗

Linux操作系统以其高度的灵活性和可定制性而闻名&#xff0c;有许多不同的发行版适用于各种场合和需求。其中一种备受欢迎的桌面环境是KDE Plasma&#xff0c;它提供了现代化的外观、丰富的功能和高度自定义的选项。那么&#xff0c;你知道哪些Linux发行版采用了KDE Plasma呢&a…

python遍历整个网站寻找所有输入框并提交表单

文章目录 一、遍历查找网站所有输入框二、对找到的输入框实现自动表单提交三、实现留言板和其他输入框的表单提交 一、遍历查找网站所有输入框 # 查找所有表单 import requests from bs4 import BeautifulSoup import sys# 定义起始页面 url sys.argv[1]# 通过requests库获取…

Linux下如何部署Nuxt项目(二)

Linux下如何部署Nuxt项目(一)_小鸟哗啦啦的博客-CSDN博客&#xff0c;书接上回&#xff0c;以实际场景开始。 请认真看完这篇文章&#xff0c;还不会部署Nuxt&#xff0c;我直接拿弹弓打你们家玻璃&#xff01; 一、nuxt的配置检查 服务端渲染的应用&#xff0c;应该是先编译构…

智能手表学习笔记

一、相关知识模块 1、RTOS & FreeRTOS &#xff08;1&#xff09; RTOS 实时操作系统&#xff08;Real Time Operating System&#xff09; 是指当外界事件或数据产生时&#xff0c;能够接受并以足够快的速度予以处理&#xff0c;其处理的结果又能在规定的时间之内来控制…

信号完整性分析基础知识之有损传输线、上升时间衰减和材料特性(二):损耗的来源

导体电阻和趋肤深度 信号沿信号路径和返回路径传播的串联电阻与导体的体电阻率和电流传播的横截面有关。直流时&#xff0c;信号导体中的电流分布均匀&#xff0c;电阻为&#xff1a; ρ表示电阻的体电阻率&#xff0c;w表示线宽&#xff0c;t表示导体厚度&#xff0c;Len表示走…

7.10蓝桥杯刷题

public class _求阶乘和 {public static void main(String[] args) {// 根据已有的知识 可以知道的是&#xff0c;现在要求s的末尾九位数字&#xff0c;已知的是39之后的阶乘他的后九位都是0;//所以不需要计算到2023的阶乘//一个数求出来的阶乘想要末尾有0//数中必须要有2和5&a…

C语言每日一练(3)

C 练习实例6 题目&#xff1a;用*号输出字母C的图案。 程序分析&#xff1a;可先用*号在纸上写出字母C&#xff0c;再分行输出。 程序源代码&#xff1a; #include "stdio.h" int main() {printf("用 * 号输出字母 C!\n");printf(" ****\n")…

小红书数据分析工具|年轻人入玄门?小红书热门笔记大赏

当代年轻人血脉觉醒&#xff0c;逐渐出现寺庙打卡、电子木鱼、发疯语录“在上进和上班之间&#xff0c;选择上香”&#xff0c;小编观察近期彩票成为年轻人信仰的新玄学&#xff0c;兴起了“送礼就送刮刮乐”的小风潮。卷不动躺不平的年轻人&#xff0c;严重精神内耗下&#xf…

Pycharm中设置动态模板(自定义自动补齐)

Settings——Editor——Live Template——点击号新增动态模板 Abbreviation缩略词&#xff1a;输入的简写内容 Template text: 简写词对应的模板内容 默认输入简写内容按Tab键&#xff0c;生成模板内容 Define: 选择在哪个语言环境下生效

【WebSocket】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 3.1 介绍3.2 入门案例3.2.1 案例分析3.2.2 代码开发3.2.3 功能测试 4. 来单提醒4.1 需求分析和设计4.2 代码开发4.3 功能测试 5. 客户催单5.1 需求分析和设计5.2 代…

接口自动化测试,一键快速校验接口返回值全部字段

目录 前言&#xff1a; 一、认识一下&#xff0c;DeepDiff 介绍 主要组成部分&#xff1a; 二、DeepDiff 使用 2.1 案例一&#xff1a;比较两个 JSON 2.2 案例二&#xff1a;比较接口响应 2.3 案例三&#xff1a;正则搜索匹配 三、最后一个小技巧&#xff1a;DeepDiff …

【代码随想录 | Leetcode | 第二天】数组 | 双指针法 | 相向双指针 | 27

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来双指针法和相向双指针的分享✨ 目录 前言27. 移除元素 27. 移除元素 ✨题目链接点这里 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于val的元素&#xff0c;并返回…

keep-alive和router-view配合使用缓存整个路由页面以及路由切换

实现内容&#xff1a;通过vue实现&#xff0c;在页面有侧边栏动态来展示当前页面流程&#xff0c;右边进行页面的切换&#xff0c;左右两边都是组件&#xff0c;但是A/B/C组件的切换是通过keep-alive搭配router-view实现的&#xff0c;首先在当前文件中创建五个文件&#xff1a…

Linux系统编程(传统信号和实时信号)

文章目录 前言一、传统信号和实时信号概念二、重要函数介绍三、实时信号和传统信号被处理的次数总结 前言 本篇文章我们来讲解传统信号和实时信号&#xff0c;这里我们将从实际应用给大家讲解。 一、传统信号和实时信号概念 传统信号&#xff08;Traditional Signals&#x…

spring boot学习第一篇:spring boot 1.5.x版本启动接口服务

1、pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…

华为云出品《IDEA-Plugin-开发手册》电子书——学完即会场景设计

小智又来给各位开发者送书啦&#xff01; 助力各位开发者们提升技能 海量案例串联 IEDA Plugin 插件开发技能 重实践与验证帮助避免踩坑 学完就可自己完成一些场景设计和开发 适合有一定编程基础&#xff0c;1年以上经验的开发者 适合对IDEA Plugin有学习需求或想拓展业务…

出海企业系列风险分析--网站需要验证码吗?

最近接待了几位从discuz来的用户&#xff0c;说是想要给自己海外的网站安装验证码&#xff0c;但是discuz境外服务器还要解析安装中心的DNS到境外服务器上&#xff0c;所以基于discuz建站的不好之处就在这里。 而且我们还讨论到一个问题&#xff0c;海外的网站&#xff0c;需要…

【线程概念和线程控制】

目录 1 :peach:线程概念 :peach:1.1 :apple:什么是线程&#xff1f;:apple:1.2 :apple:线程的优点和缺点:apple:1.3 :apple:页表的大小:apple:1.4 :apple:线程异常和用途:apple:1.5 :apple:进程VS线程:apple: 2 :peach:线程控制:peach:2.1 :apple:POSIX线程库:apple:2.2 :apple…

tp6的runtime/Logs目录下产生大量日记文件,怎么取消自动生成?

一开始查了好多网上提供的&#xff0c;很幸运都是抄袭别人的&#xff0c;没一个成功&#xff0c;最后无奈只能自己解决方法 其实很简单&#xff0c;不用修改config/log.php文件&#xff0c;没用因为只要有登入错误&#xff0c;警告&#xff0c;消息或者sql错误都会写入 解决方…