设计模式(JAVA)——Memento模式

1. Memento模式

使用面向对象编程方式实现撤销功能时,需要事先保存实例的相关状态信息。然后,在撤销时,还需要根据所保存的信息将实例恢复至原来的状态。

Memento的意思:“备忘录”、“纪念品”

其做的功能可能是:

  • 撤销(Undo)
  • 重做(Redo)
  • 历史记录(History)
  • 快照(Snapshot)

1.1 Memento模式的类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VaykHCpu-1574942245191)(./resources/image/18/18-1_Memento.png)]

登场角色:

  • Originator(生成者)
    Originator就是需要被保存,被记录快照的对象。其含有生成Memento和恢复Memento的方式

  • Memento(纪念品)
    Originator的快照

  • Caretaker(负责人)
    Caretaker决定了在什么时候调用Originator的方法,即什么是时候调用Originator方法生成Memento的策略

1.2 示例程序

类一览表:

名字说明
Memento表示Gamer状态的类
Gamer一个游戏类
Main进行游戏,会调用Gamer的方式生成Memento

uml类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PtieneeY-1574942245193)(./resources/image/18/18-2.png)]

Memento类

package xin.ajay.memento;

import java.util.ArrayList;
import java.util.List;

public class Memento {
    private int money;
    private List<String> fruits = new ArrayList<>();

    public int getMoney() {
        return money;
    }


    public void addFruit(String fruit){
        fruits.add(fruit);
    }


    public List<String> getFruits(){
        return fruits;
    }

    public Memento(int money) {
        this.money = money;
    }
}

Gamer类

package xin.ajay.memento;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

public class Gamer {
    /*
     游戏规则:

     玩家通过掷骰子决心下一个状态

     点数为1 金钱增加
     点数为2 金钱减少
     点数为6 获得水果
     当money为0时,游戏结束
     */

    private int money;
    private List<String> fruits = new ArrayList<>();

    private Random random = new Random();
    private static String[] fruitsname = {"苹果", "香蕉", "橘子", "葡萄"};

    public Gamer(int money) {
        this.money = money;
    }

    public int getMoney() {
        return money;
    }

    public void bet() {
        int i = random.nextInt(6) + 1;
        switch (i) {
            case 1:
                money += 100;
                System.out.println("金钱增加了");
                break;
            case 2:
                money /= 2;
                System.out.println("金钱减少了");
                break;
            case 6:
                String fruit = getFruit();
                fruits.add(fruit);
                System.out.println("获得水果(" + fruit + ")。");break;
                default:
                    System.out.println("什么都没发生");
        }
    }


    //拍摄快照
    public Memento createMemento(){
        Memento memento = new Memento(money);

        //保存逻辑
        for (String f : fruits) {
            if (f.startsWith("好吃的")) {
                memento.addFruit(f);
            }
        }

        return memento;
    }

    private String getFruit() {
        String prefix = "";
        if (random.nextBoolean()) {
            prefix = "好好的";
        }
        return prefix + fruitsname[random.nextInt(fruitsname.length)];
    }

    @Override
    public String toString() {
        return "Gamer{" + "money=" + money + ", fruits=" + fruits + '}';
    }

    public void restoreMemento(Memento memento) {
        this.money = memento.getMoney();
        this.fruits = memento.getFruits();
    }
}

Main类

package xin.ajay.memento;

public class Main {

    public static void main(String[] args) {
        Gamer gamer = new Gamer(100);
        Memento memento = gamer.createMemento();//保持状态


        for (int i = 0; i < 10; i++) {
            System.out.println("==== "+i);
            System.out.println("当前状态: " + gamer);

            gamer.bet();//进行游戏

            System.out.println("所持金钱为" + gamer.getMoney() +"元。");


            //在什么状态生成快照逻辑和恢复快照
            if(gamer.getMoney() > memento.getMoney()){
                System.out.println("    (所持金钱增加了,因此需要保存当前的状态)");
                memento = gamer.createMemento();
            }else if(gamer.getMoney() < memento.getMoney()/2){
                System.out.println("    (所持金钱减少了许多,因此需要将游戏恢复至以前的状态)");
                gamer.restoreMemento(memento);
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
鸣谢:

GoF《设计模式》和结城浩的《图解设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值