GoF之备忘录模式、解释器模式详解

备忘录(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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值