摘要:本文用一个实例场景描述Gof 23设计模式中的备忘录(Memento)模式,并用Quarkus框架代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 备忘录模式 Quarkus
1 基础知识
1.1 标准定义
备忘录(Memento)模式标准定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
1.2 分析和说明
备忘录(Memento)模式属于对象行为型模式。备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
Memento结构如图1所示,其角色包括发起人(Originator)角色和负责人(Caretaker)角色。
图1 备忘录模式结构
发起人(Originator)角色,发起人角色有如下的责任:① 创建一个含有当前的内部状态的备记录对象。② 使用备忘录对象存储其内部状态。
负责人(Caretaker)角色,负责人角色有如下的责任:① 负责保存备忘录对象。② 不检查备忘录对象的内容。
2 应用场景举例
公司领导在每周周一都要召开项目会议,每次会议后都有会议纪要。会议纪要都要把现阶段项目情况汇总起来。这些项目情况就是备忘录,上面有时间戳这个标志。实现用例见图2所示。
图2 备忘录模式用例图
在这里可以把Meeting类理解为发起人(Originator)角色。Caretaker类是负责人(Caretaker)角色。其实现类图如图3所示。Memento类与Caretaker类的关系是聚合关系,即Caretaker类拥有多个Memento类。
图3 备忘录模式类图
备忘录模式实现顺序图见图4,实现顺序描述:① 基于Meeting类创建一个meet1对象;② 调用meet1对象的createMemento方法创建memento对象;③ 基于Caretaker类创建一个caretaker对象;④ 调用caretaker对象的saveMemento方法,把memento对象存入caretaker对象。
图4 备忘录模式实现顺序图
3.Quarkus的实现程序代码
Quarkus程序实现主要包括Meeting类文件,Caretaker类文件和Memento类文件等3个文件。其关系如图3所示。下面分别列出这3个文件的程序代码,最后列出测试代码并显示输出结果。
Meeting类程序代码清单01所示。
程序代码清单01
@Dependent
public class Meeting {
private String meetName;
private String meetType;
private String meetdate;
private String meetLeader;
private String meetParticipants;
private String decide;
private String meetContent;
public Meeting(){}
public String getMeetName() {
return meetName;
}
public void setMeetName(String meetName) {
this.meetName = meetName;
}
public String getMeetType() {
return meetType;
}
public void setMeetType(String meetType) {
this.meetType = meetType;
}
public String getMeetdate() {
return meetdate;
}
public void setMeetdate(String meetdate) {
this.meetdate = meetdate;
}
public String getMeetLeader() {
return meetLeader;
}
public void setMeetLeader(String meetLeader) {
this.meetLeader = meetLeader;
}
public String getMeetParticipants() {
return meetParticipants;
}
public void setMeetParticipants(String meetParticipants) {
this.meetParticipants = meetParticipants;
}
public String getDecide() {
return decide;
}
public void setDecide(String decide) {
this.decide = decide;
}
public String getMeetContent() {
return meetContent;
}
public void setMeetContent(String meetContent) {
this.meetContent = meetContent;
}
public void doDecide() {
meetContent = "会议名称:" + meetName + ";";
meetContent = meetContent + "会议类型:" + meetType + ";";
meetContent = meetContent + "会议时间:" + meetdate + ";";
meetContent = meetContent + "会议主持人:" + meetLeader + ";";
meetContent = meetContent + "会议参加者:" + meetParticipants + "\r";
meetContent = meetContent + "会议内容:" + meetParticipants + ";";
}
public Memento CreateMemento() {
Memento mo = new Memento(meetName, meetType, meetdate, meetLeader,
meetParticipants, decide, meetContent);
return mo;
}
public void recoveryMemento(Memento mo){
meetName = mo.getMeetName();
meetType = mo.getMeetType();
meetdate = mo.getMeetdate();
meetLeader = mo.getMeetLeader();
meetParticipants = mo.getMeetParticipants();
decide = mo.getDecide();
meetContent = mo.getMeetContent();
}
public void showContent(){
System.out.println(meetContent);
}
}
Caretaker类程序代码清单02所示。
程序代码清单02
@ApplicationScoped
public class Caretaker {
private Map<String, Memento> meetMementoMap = new HashMap<String, Memento>();
public Memento recoveryMemento(String meetdate) {
return meetMementoMap.get(meetdate);
}
public void saveMemento(String meetdate, Memento memento) {
this.meetMementoMap.put(meetdate, memento);
}
public void showContent(){
System.out.println("显示全部的会议情况:");
String meetdate;
String meetContent;
Iterator<String> it = meetMementoMap.keySet().iterator();
while (it.hasNext()){
meetdate = it.next();
meetContent = meetMementoMap.get(meetdate).getMeetContent();
System.out.print(meetdate+";"+meetContent);
System.out.println();
}
}
}
Memento类程序代码清单03所示。
程序代码清单03
public class Memento {
private String meetName;
private String meetType;
private String meetdate;
private String meetLeader;
private String meetParticipants;
private String decide;
private String meetContent;
public Memento(String meetName, String meetType, String meetdate,String meetLeader,
String meetParticipants, String decide,String meetContent) {
super();
this.meetName = meetName;
this.meetType = meetType;
this.meetdate = meetdate;
this.meetLeader = meetLeader;
this.meetParticipants = meetParticipants;
this.decide = decide;
this.meetContent = meetContent;
}
public void showContent(){System.out.println(meetContent);}
public String getMeetName() {return meetName; }
public void setMeetName(String meetName) {this.meetName = meetName; }
public String getMeetType() {return meetType;}
public void setMeetType(String meetType) { this.meetType = meetType;}
public String getMeetdate() { return meetdate;}
public void setMeetdate(String meetdate) {this.meetdate = meetdate;}
public String getMeetLeader() {return meetLeader;}
public void setMeetLeader(String meetLeader) {this.meetLeader = meetLeader; }
public String getMeetParticipants() {return meetParticipants;}
public void setMeetParticipants(String meetParticipants) {this.meetParticipants = meetParticipants; }
public String getDecide() {return decide;}
public void setDecide(String decide) {this.decide = decide; }
public String getMeetContent() {return meetContent;}
public void setMeetContent(String meetContent) {this.meetContent = meetContent; }
}
备忘录模式测试程序的代码清单04如下:
程序代码清单04
public class MementoClient implements QuarkusApplication {
@ConfigProperty(name = "gof23.behavioralpattern.memento.title", defaultValue = "gof23")
String title;
@Inject Meeting meet1,meet2 ;
@Inject Caretaker caretaker;
@Override
public int run(String... args) {
System.out.println("——————" + title + "演示输出———————");
meet1.setMeetName("meetName1");
meet1.setMeetType("meetType1");
meet1.setMeetdate("2009-01-01");
meet1.setMeetLeader("meetLeader1");
meet1.setMeetParticipants("meetParticipants1");
meet1.setDecide("decide1");
meet1.doDecide();
Memento memento = meet1.CreateMemento();
caretaker.saveMemento(memento.getMeetdate(),memento);
meet2.setMeetName("meetName2");
meet2.setMeetType("meetType2");
meet2.setMeetdate("2009-02-01");
meet2.setMeetLeader("meetLeader2");
meet2.setMeetParticipants("meetParticipants2");
meet2.setDecide("decide2");
meet2.doDecide();
memento = meet2.CreateMemento();
caretaker.saveMemento(memento.getMeetdate(),memento);
caretaker.showContent();
return 0;
}
public static void main(String... args) {
Quarkus.run(MementoClient.class, args);
}
}
备忘录模式测试类输出结果如下所示:
显示全部的会议情况:
2009-01-01;会议名称:meetName1;> 会议类型:meetType1;> 会议时间:2009-01-01;会议主持人:meetLeader1;会议参加者:meetParticipants1>
会议内容:meetParticipants1;
2009-02-01;会议名称:meetName2;会议类型:meetType2;会议时间:2009-02-01;会议主持人:meetLeader2;会议参加者:meetParticipants2
会议内容:meetParticipants2;
4. 相关Quarkus程序源码下载
可以直接从github上获取代码,读者可以从github上clone预先准备好的示例代码。
git clone https://github.com/rengang66/quarkus-sample-gof23.git
这是一个Maven项目,然后Maven导入工程。该程序位于“src\main\java\com\iiit\quarkus\sample\gof23\behavioralpattern\memento”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:
git clone https://gitee.com/rengang66/quarkus-sample-gof23.git
参考文献
[1] E.Gamma, R.Helm, R.Johnson, and Vlissides. Design Patterns Elements of Reusable Object Oriented Software. Addison-Wesley, 1995
[2] E.Gamma, R.Helm, R.Johnson, and Vlissides.著,李英军等译,设计模式:可复用面向对象软件的基础,北京:机械工业出版社.2000.9.
[3] 阎宏,Java与模式,北京:电子工业出版社. 2002.10
[4] 王俊峰 戚晓滨. 设计模式和UML. 计算机应用研究,1999.16(5), 27-29,39.
[5] 陈琴 朱正强. UML在设计模式描述中的应用. 计算机工程与设计,2003.24(4), 81-84.
[6] 刘红军. J2ME手机日记本的设计原理与关键技术. 电脑编程技巧与维护,2008.(10), 43-46.
[7] 张昊 王彦桂 唐去克. 监控绘图软件中Undo/Redo的设计和实现. 自动化与信息工程,2008.29(1), 23-25.
[8] 韩小俊 王珂. 矢量图软件中Undo/Redo操作. 电脑编程技巧与维护,2007.(3), 63-65.
[9] 曾志明[1,2] 朱江[1,2] 张立立[1,2] 钟耳顺[1]. 设计模式在可复用GIS软件开发中的应用. 计算机工程,2006.32(7), 67-68,77.
[10] Quarkus官网. https://quarkus.io/