备忘录(Memento Pattern)模式
在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
优点:
1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:
消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
优使用场景:
1、需要保存/恢复数据的相关状态场景。
2、提供一个可回滚的操作。
3、为遍历不同的聚合结构提供一个统一的接口。
具体实现:创建三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。
为了节约内存,使用原型模式+备忘录模式。
//Memento类,用于包含对象状态
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
//Originator类,负责在Memento中储存状态
public class Originator{
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento Memento) {
state =Memento.getState();
}
}
//CareTaker类,负责添加对象至容器中,和从 Memento 中恢复对象的状态
public class CareTaker {
private ListmementoList =new ArrayList();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
//使用 CareTaker 和 Originator 对象
public class Client {
public static void main(String[] args) {
Originatororiginator = new Originator();
CareTaker careTaker = newCareTaker();
originator.setState(“State#1”)
originator.setState(“State#2”);
careTaker.add(originator.saveStateToMemento());
originator.setState(“State#3”);
careTaker.add(originator.saveStateToMemento());
originator.setState(“State#4”)
System.out.println("CurrentState: " + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("Firstsaved State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Secondsaved State: " + originator.getState());
}
}
/*
CurrentState: State #4
First savedState: State #2
Secondsaved State: State #3
*/
解释器(InterpreterPattern)模式
给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
优点:
1、可扩展性比较好,灵活。
2、增加了新的解释表达式的方式。
3、易于实现简单文法。
缺点:
1、可利用场景比较少。
2、对于复杂的文法比较难维护。
3、解释器模式会引起类膨胀。
4、解释器模式采用递归调用方法。
使用场景:
1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
2、一些重复出现的问题可以用一种简单的语言来进行表达。
3、一个简单语法需要解释的场景。
具体实现:假如“武汉通”公交车读卡器可以判断乘客的身份,如果是“汉口”或者“武昌”的“老人”“妇女”“儿童”就可以免费乘车,其他人员乘车一次扣 2 元。。
//抽象表达式类
interface Expression {
//解释方法
public boolean interpret(String info);
}
//终结符表达式类
class TerminalExpressionimplements Expression{
private Setset = new HashSet();
public TerminalExpression(String[]data) {
for (int i = 0; i < data.length; i++) set.add(data[i]);
}
public boolean interpret(String info) {
if (set.contains(info)) {
return true;
}
return false;
}
}
//非终结符表达式类
class AndExpression implements Expression {
private Expression city = null;
private Expression person = null;
public AndExpression(Expressioncity, Expressionperson) {
this.city = city;
this.person = person;
}
public boolean interpret(String info) {
String s[] = info.split("的");
return city.interpret(s[0]) && person.interpret(s[1]);
}
}
//环境类
class Context {
private String[] citys = {“汉口”, “武昌”};
private String[] persons = {“老人”, “妇女”, “儿童”};
private Expression cityPerson;
//数据初始化
public Context() {
Expressioncity = new TerminalExpression(citys);
Expression person = new TerminalExpression(persons);
cityPerson = new AndExpression(city, person);
}
//调用相关表达式类的解释方法
public void freeRide(String info) {
boolean ok = cityPerson.interpret(info);
if (ok) System.out.println(“您是” + info + “,您本次乘车免费!”);
else System.out.println(info + “,您不是免费人员,本次乘车扣费2元!”);
}
}
public class Client {
public static void main(String[] args) {
Context bus =new Context();
bus.freeRide(“汉口的老人”);
bus.freeRide(“汉口的年轻人”);
bus.freeRide(“武昌的妇女”);
bus.freeRide(“武昌的儿童”);
bus.freeRide(“湖南的儿童”);
}
}
/*
程序运行结果如下:
您是武汉的老人,您本次乘车免费!
武汉的年轻人,您不是免费人员,本次乘车扣费2元!
您是武昌的妇女,您本次乘车免费!
您是武昌的儿童,您本次乘车免费!
湖南的儿童,您不是免费人员,本次乘车扣费2元!
*/
更多技术分享,公众号“专注一行代码”,ID zzyhdm