天天看點

備忘錄模式執行個體象棋中“悔棋”操作

1.題目分析

首先需要一個實體類來代表一枚象棋的基本資訊,包含象棋的名字/目前坐标

其次需要一個備忘錄類來儲存象棋的資訊,這個類應當含有象棋類的要儲存的字段,并且該類對外封閉

由于備忘錄類是對外封閉的,是以應當由一個備忘錄管理者類,來負責建立和恢複象棋的備忘錄

用戶端不與備忘錄類耦合,而是借用備忘錄管理類來管理備忘錄

2.UML圖

備忘錄模式執行個體象棋中“悔棋”操作

3.代碼

象棋實體類

package 備忘錄模式;

public class Chessman {
    private String name;
    private int x;
    private int y;
    public ChessmanMemento CreateMemento() {
        return new ChessmanMemento(name, x, y);
    }
    public void setMemento(ChessmanMemento chessmanMemento) {
        this.name = chessmanMemento.getName();
        this.x = chessmanMemento.getX();
        this.y = chessmanMemento.getY();
    }
    public Chessman() {
    }

    public Chessman(String name, int x, int y) {
        this.name = name;
        this.x = x;
        this.y = y;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public String toString() {
        return "Chessman{" +
                "name='" + name + '\'' +
                ", x=" + x +
                ", y=" + y +
                '}';
    }
}      

象棋備忘錄 用于儲存象棋的狀态資訊

package 備忘錄模式;

public class ChessmanMemento {
    private String name;
    private int x;
    private int y;

    public ChessmanMemento(String name, int x, int y) {
        this.name = name;
        this.x = x;
        this.y = y;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
    
}      

備忘錄負責人 管理備忘錄 隐藏備忘錄内部實作

package 備忘錄模式;

public class MementoCaretaker {
      private ChessmanMemento chessmanMemento;

      public ChessmanMemento getChessmanMemento() {
          return chessmanMemento;
      }

      public void setChessmanMemento(ChessmanMemento chessmanMemento) {
          this.chessmanMemento = chessmanMemento;
      }
}      

象棋悔棋備忘錄測試類

package 備忘錄模式;

public class Test {

    public static void main(String[] args) {
        
        Chessman chessman = new Chessman("馬", 1, 1);
        System.out.println("象棋初始狀态-->" + chessman);
        MementoCaretaker mementoCaretaker = new MementoCaretaker();
        mementoCaretaker.setChessmanMemento(chessman.CreateMemento());
        chessman.setX(666);
        chessman.setY(666);
        System.out.println("象棋修改狀态-->" + chessman);
        chessman.setMemento(mementoCaretaker.getChessmanMemento());
        System.out.println("象棋恢複狀态-->" + chessman);

    }
}      

運作結果

備忘錄模式執行個體象棋中“悔棋”操作
  1. 該模式的優缺點,特别從開閉原則論述

    優點:利用備忘錄管理者類,保持了象棋的封閉性,沒有破壞其封裝。儲存了象棋的内部狀态,以便在需要的時候恢複狀态

    缺點:如果類的資訊太多,會十分消耗資源

  2. 程式設計中遇到的問題及解決方法:

    該模式在不同的場景下有改進的幾個方面,比如:備忘錄管理者類,其字段備忘錄可以改為一個Map類型的,key為唯一的字段屬性,value為儲存的備忘錄對象,這樣就可以根據Key來恢複任意一個狀态,Github的版本控制就是這個原理,每一個版本都有對應的一個哈希串,可以回退到任意一個版本。

    可以結合原型模式+備忘錄來處理相應的需求,以減少資源的消耗