java设计模式之备忘录

一.简介

话说,我小时候玩小霸王游戏中坦克大战的闯关游戏中,哪个时候我们基本上每次过了一关都会保存进度,如果不玩了,或者是下一关太难过了每过了,这样我们就可以回到原先的时候,回到原先的进度继续游戏.这样我们就回到过去了.

二.结构

  • 备忘录(Memento)角色:备忘录角色存储"备忘发起者角色"的内部状态;在黑箱和自述历史模式的情况下,不允许除了发起人之外的人访问自己.
  • 备忘发起者角色:创建一个备忘录,在需要还原的时候,还原备忘录内部状态;
  • 备忘录管理者角色:负责保存好备忘录.

三.代码

白箱,外部可以访问,简单而言,就是没有进行封装.
public class Memorandum {

    public static void main(String[] args) {
        // 发起者
        Sponsor sponsor = new Sponsor();
        // 管理者
        Manager manager = new Manager();

        // 设置内容
        sponsor.setText("abc");
        // 记录版本
        sponsor.createManager(manager, 1);
        // 修改内容
        sponsor.setText("abcdef");
        // 记录版本
        sponsor.createManager(manager, 2);

        // 修改内容
        sponsor.setText("abcdefgh");
        // 记录版本
        sponsor.createManager(manager, 3);

        // 回滚到版本1
        sponsor.callBackToVersion(manager, 1);
        System.out.println("第一个版本的内容是:" + sponsor.getText());
        // 回滚到版本2
        sponsor.callBackToVersion(manager, 2);
        System.out.println("第一个版本的内容是:" + sponsor.getText());
    }
}

// 操作角色 文本编辑
class TextEdit {
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
// 管理者
class Manager {
    private Map<Integer, TextEdit> map = new HashMap<>();

    public TextEdit getTextEdit(Integer version) {
        return map.get(version);
    }

    // 每次取出最新的版本
    public void setTextEdit(TextEdit baby, Integer version) {
        map.put(version, baby);
    }
}
// 发起者
class Sponsor {
    private String text;
    // 保存状态
    public Manager createManager(Manager manager, Integer version) {
        TextEdit edit = new TextEdit();
        edit.setText(text);
        manager.setTextEdit(edit, version);
        return manager;
    }
    // 回滚到指定版本
    public void callBackToVersion(Manager manager, Integer version) {
        text = manager.getTextEdit(version).getText();
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
//output
//第一个版本的内容是:abc
//第一个版本的内容是:abcdef
黑箱,外部不能操作备忘录角色,它更符合我们编程的开闭原则,对外开放访问,关闭修改.只有发起人才能对备忘角色进行修改,管理者或者是其他类不能对备忘录角色进行修改.

public class Memorandum {

    public static void main(String[] args) {
        // 发起者
        Sponsor sponsor = new Sponsor();
        // 管理者
        Manager manager = new Manager();

        // 设置内容
        sponsor.setText("abc");
        // 记录版本
        sponsor.createManager(manager, 1);
        // 修改内容
        sponsor.setText("abcdef");
        // 记录版本
        sponsor.createManager(manager, 2);
        // 修改内容
        sponsor.setText("abcdefgh");
        // 记录版本
        sponsor.createManager(manager, 3);

        // 回滚到版本1
        sponsor.callBackToVersion(manager, 1);
        System.out.println("第一个版本的内容是:" + sponsor.getText());
        // 回滚到版本2
        sponsor.callBackToVersion(manager, 2);
        System.out.println("第一个版本的内容是:" + sponsor.getText());

    }

}


// 定义接口,让备忘录角色实现,此接口为了让管理者去操作
interface A {}
// 管理者 它不能看到备忘录角色的具体的内容,因为它操作的是接口
class Manager {
    private Map<Integer, A> map = new HashMap<>();

    public A getTextEdit(Integer version) {
        return map.get(version);
    }

    // 每次取出最新的版本
    public void setTextEdit(A baby, Integer version) {
        map.put(version, baby);
    }
}

// 发起者 能知道备忘录角色的具体类容,因为备忘录角色是它的私有类
class Sponsor {
    private String text;
    // 保存状态
    public Manager createManager(Manager manager, Integer version) {
        TextEdit edit = new TextEdit(text);
        manager.setTextEdit(edit, version);
        return manager;
    }
    // 回滚到指定版本
    public void callBackToVersion(Manager manager, Integer version) {
        text = ((TextEdit) manager.getTextEdit(version)).getText();
    }
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    // 备忘录角色,实现了窄接口
    // 注意:此类的所有属性都是私有
    private class TextEdit implements A {
        private String text;
        private TextEdit(String text) {
            this.text = text;
        }
        private String getText() {
            return text;
        }

        private void setText(String text) {
            this.text = text;
        }
    }
}
// output
//第一个版本的内容是:abc
//第一个版本的内容是:abcdef
自述历史模式,此模式把负责人和发起人放到一个类中,这是在开发中使用的最常用的


public class Memorandum {

    public static void main(String[] args) {
        // 发起人与负责人
        Sponsor sponsor = new Sponsor();
        // 设置内容
        sponsor.setText("abc");
        // 记录版本
        sponsor.createManager(1);
        // 修改内容
        sponsor.setText("abcdef");
        // 记录版本
        sponsor.createManager(2);
        // 修改内容
        sponsor.setText("abcdefgh");
        // 记录版本
        sponsor.createManager(3);

        // 回滚到版本1
        sponsor.callBackToVersion(1);
        System.out.println("第一个版本的内容是:" + sponsor.getText());
        // 回滚到版本2
        sponsor.callBackToVersion(2);
        System.out.println("第一个版本的内容是:" + sponsor.getText());

    }

}

// 发起者+负责人 能知道备忘录角色的具体类容,因为备忘录角色是它的私有类
class Sponsor {
    private String text;

    private Map<Integer, TextEdit> map = new HashMap<>();

    //    每次取出最新的版本
    private TextEdit getTextEdit(Integer version) {
        return map.get(version);
    }

    // 保存版本
    private void setTextEdit(TextEdit baby, Integer version) {
        map.put(version, baby);
    }


    // 保存状态
    public void createManager(Integer version) {
        TextEdit edit = new TextEdit(text);
        setTextEdit(edit, version);
    }

    // 回滚到指定版本
    public void callBackToVersion(Integer version) {
        text = getTextEdit(version).getText();
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    // 备忘录角色,被发起者私有
    // 注意:此类的所有属性都是私有
    private class TextEdit {
        private String text;

        private TextEdit(String text) {
            this.text = text;
        }
        private String getText() {
            return text;
        }
    }
}
// output
//第一个版本的内容是:abc
//第一个版本的内容是:abcdef


四.应用场景

  • 必须保存某一个对象某个或者多个时刻的状态,以方便我们以后使用的时候回复到以前的状态;
  • 如果用一个接口让其他对象直接得到这些状态,江湖暴露对象的实现细节并且破环对象的封装型.

五.各个角色的作用

  • 备忘录角色:将发起人角色的内部状态存储下来,备忘录能根据发起人判断应该存储多少备忘录.能保护内容不被发起人之外的对象读取;
  • 发起人角色:创建一个含有当前内部状态的备忘录角色,使用备忘录角色存储其内部状态;
  • 负责人角色:保存备忘录角色;

六.参考文献

大话设计模式



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值