备忘录模式是用于保存对象在某个时刻的状态,来实现撤销操作。而解释器模式则是将文本按照定义的文法规则解析成对应的命令。
需求:保存对象在某个时刻的状态,后面可以对该对象实行撤销操作。
提供一种状态恢复机制,在不破坏封装的前提下,捕获对象内部状态并在该对象之外保存这个状态。可以在以后将对象恢复到原先保存的状态。
图 备忘录模式 UML
- public class MementoPattern {
-
- public static void main(String[] args) {
- String[] colors = {"red","blue","green","pink","black"};
- Button button = new Button();
- Random random = new Random();
- MementoCareTaker<ButtonMemento> careTaker = new MementoCareTaker<>();
- for (int i = 0; i < 10; i++) {
- button.setColor(colors[random.nextInt(colors.length)]);
- button.setPositionX(random.nextDouble());
- careTaker.pushMemento(button.createMemento());
- }
- button.restoreFromMemento(careTaker.getMemento(2));
- System.out.println(button);
- button.restoreFromMemento(careTaker.getMemento(3));
- System.out.println(button);
- button.restoreFromMemento(careTaker.getMemento(1));
- System.out.println(button);
- }
-
- private static class Button {
- private String color;
- private Double positionX;
-
- public String getColor() {
- return color;
- }
-
- public void setColor(String color) {
- this.color = color;
- }
-
- public Double getPositionX() {
- return positionX;
- }
-
- public void setPositionX(Double positionX) {
- this.positionX = positionX;
- }
-
- public ButtonMemento createMemento() {
- return new ButtonMemento(color,positionX);
- }
-
- public void restoreFromMemento(ButtonMemento memento) {
- this.color = memento.getColor();
- this.positionX = memento.positionX;;
- }
-
- @Override
- public String toString() {
- return "Button{" +
- "color='" + color + '\'' +
- ", positionX=" + positionX +
- '}';
- }
- }
-
- private static class ButtonMemento {
- private final String color;
- private final Double positionX;
-
- public ButtonMemento(String color, Double positionX) {
- this.color = color;
- this.positionX = positionX;
- }
-
- public String getColor() {
- return color;
- }
-
- public Double getPositionX() {
- return positionX;
- }
-
- }
-
- private static class MementoCareTaker
{ -
- private final Stack
stack = new Stack<>(); -
- public void pushMemento(T t) {
- stack.push(t);
- }
-
- public T getMemento(int num) {
- T t = null;
- while (num-- > 0 && !stack.isEmpty()) {
- t = stack.pop();
- }
- return t;
- }
-
- }
-
- }
优点:
缺点:
需求:将文本按照特定的语法规则转换成计算机中特定的命令。
定义一个语言的文法,并建立一个解释器来解释该语言中的句子。这里的“语言”是指使用特定格式和语法的代码。
图 解释器UML
这里的Context 一般用于存储解释器之外的一些全局信息,也可以省略这个类。
::= | 定义为。 |
| | 或。 |
‘{’和‘}’ | 组合。 |
* | 出现0或多次。 |
语言单位 | 语言构造成分,每一条语句所定义的字符串。 |
终结表达式 | 组成元素是最基本的语言单位,不能在进行分解。 |
非终结表达式 | 组成元素仍可以是表达式,可进一步分解。 |
图 文法规则说明
- public class InterpreterPattern {
- /**
- * 语法规则:
- * value ::= a integer
- * operator ::= '+' | '-' | '*' | '/'
- * expression ::= value operator value | complexExpression
- * complexExpression ::= expression operator expression | expression operator (expression)
- */
- public static void main(String[] args) {
- String[] textArr = {"1+4*3","4*5+3","(3+4)*23", "(3+24)-(23-8)", "(2-3)*(24+2*3)", "(((1+2)*(2+3)))+32"};
- for (int i = 0; i < textArr.length; i++) {
- System.out.print(textArr[i]);
- System.out.println("=" + new ComplexExpression().interpreter(textArr[i]));
- }
- }
-
- private static abstract class Expression {
- abstract int interpreter(String text);
-
- protected int compute(int leftNum,int rightNum,char opera) {
- switch (opera) {
- case '+': return leftNum + rightNum;
- case '-': return leftNum - rightNum;
- case '*': return leftNum * rightNum;
- case '/': return leftNum / rightNum;
- }
- return 0;
- }
- }
-
- /**
- * 复杂表达式
- */
- private static class ComplexExpression extends Expression {
- @Override
- int interpreter(String text) {
- // System.out.println("ComplexExpression:" + text);
- int letNum=0;
- int rightNum=0;
- char opera = ' ';
-
- Pattern pattern = Pattern.compile("[\\+\\-\\*\\/]");
- Matcher matcher = pattern.matcher(text);
- if (matcher.find()) {
- int start = matcher.start();
- opera = text.charAt(start);
- if (text.indexOf("(") == 0) { // 在操作符前面有括号, 先计算括号的内容
- int endBracketPos = findEndBracketPos(text);
- letNum = new ComplexExpression().interpreter(text.substring(1,endBracketPos));
- if (endBracketPos == text.length() -1 ) {
- return letNum;
- }
- opera = text.charAt(endBracketPos+1);
- rightNum = new ComplexExpression().interpreter(text.substring(endBracketPos+2));
- } else if ((opera == '*' || opera == '/') && text.charAt(start+1) != '(') { // 需要先完成左边运算
- boolean hasNext = matcher.find(start + 1);
- if (hasNext) {
- int pos2 = matcher.start();
- letNum = new ComplexExpression().interpreter(text.substring(0,pos2));
- opera = text.charAt(pos2);
- rightNum = new ComplexExpression().interpreter(text.substring(pos2+1));
- } else {
- letNum = new TerminalExpression().interpreter(text.substring(0,start));
- rightNum = new ComplexExpression().interpreter(text.substring(start+1));
- }
-
- } else {
- letNum = new TerminalExpression().interpreter(text.substring(0,start));
- rightNum = new ComplexExpression().interpreter(text.substring(start+1));
- }
- return compute(letNum,rightNum,opera);
- } else { // 终结表达式
- return new TerminalExpression().interpreter(text);
- }
- }
-
- private int findEndBracketPos(String text) {
- int startPos = 0,endPos = 0;
- do {
- endPos = text.indexOf(")",endPos+1);
- startPos = text.indexOf("(",startPos+1);
- } while (startPos < endPos && startPos > 0);
- return endPos;
- }
-
- }
-
- /**
- * 是一个数值 或者 是 (数值) 形式,要把text 转换为数值
- */
- private static class TerminalExpression extends Expression {
- @Override
- int interpreter(String text) {
- // System.out.println("TerminalExpression:" + text);
- if (text.indexOf("(") == 0) {
- text = text.substring(1,text.length() - 1);
- }
- return Integer.parseInt(text);
- }
- }
-
- }
优点:
缺点: