Java设计模式--备忘录模式

备忘录模式(别名:标记)

在不破坏封装性的前提下,捕捉一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。

Memento Pattern(Another Name: Token)

Without violating encapsulation, capture and externalize an object original state so that the object can be restored to this state later.

类图

模式的结构与使用

备忘录模式的结构中包括三种角色。
+ 原发者(Originator):需要在某个时刻保存其状态的对象。原发者负责创建备忘录,比如使用createMemento()方法创建一个备忘录,然后原发者使用该备忘录记录自己的状态。当原发者需要恢复某个时刻的状态时,它通过获得相应备忘录中的数据来恢复那个时刻的状态,比如原发者调用restoreFromMemento(Memento menm)方法,并通过参数mem指定的备忘录恢复状态。
+ 备忘录(Memento):负责存储原发者状态的对象,创建备忘录的类和创建原发者的类在同一个包中,该类提供的访问数据的方法都是友好方法,使得只有和原发者在同一个包中的类的实例才可以访问备忘录中的数据。
+ 负责人(Caretaker):负责管理保存备忘录的对象。负责人如果不和原发者在同一个包中,就不能对备忘录中的内容进行修改或读取。如果需要将备忘录保存到磁盘,负责人可以使用对象流将备忘录写入文件。

简单的例子

Memento的备忘录类Memento.java

package Memento;

import java.io.Serializable;

public class Memento implements Serializable {
    private long state;

    void setPositionState(long state) {
        this.state = state;
    }

    long getPosition() {
        return state;
    }
}

一个小的工具类ReadPhrase.java

ppackage Memento;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class ReadPhrase {
    long readPosition;
    File file;
    RandomAccessFile in;
    String phrase = null;

    public ReadPhrase(File file) {
        this.file = file;
        try {
            in = new RandomAccessFile(file, "r");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public Memento createMemento() {
        Memento mem = new Memento();
        System.out.println("----" + readPosition);
        mem.setPositionState(readPosition);
        return mem;
    }

    public void restoreFromMemento(Memento mem) {
        readPosition = mem.getPosition();
    }

    public String readLine() {
        try {
            in.seek(readPosition);
            phrase = in.readLine();
            if (phrase != null) {
                byte b[] = phrase.getBytes("UTF-8");
                phrase = new String(b);
            }
            readPosition = in.getFilePointer();
            System.out.println("readPosition:" + readPosition);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return phrase;
    }

    public void closeRead() {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

负责人的类Caretaker.java

package Memento;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Caretaker {
    File file;
    private Memento memento = null;

    public Caretaker() {
        file = new File("saveObject.txt");
    }

    public Memento getMemento() {
        if (file.exists()) {
            try {
                FileInputStream in = new FileInputStream("saveObject.txt");
                ObjectInputStream inObject = new ObjectInputStream(in);
                memento = (Memento) inObject.readObject();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return memento;
    }

    public void saveMemento(Memento memento) {
        FileOutputStream out;
        try {
            out = new FileOutputStream("D:/09soft/MyEclipse 10/yanning/saveObject.txt");
            ObjectOutputStream outObject = new ObjectOutputStream(out);
            outObject.writeObject(memento);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试类Application.java

package Memento;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;

public class Application {

    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        ReadPhrase readPhrase = new ReadPhrase(new File("D:/09soft/MyEclipse 10/yanning/src/Memento/phrase.txt"));
        File favorPhrase = new File("favorPhrase.txt");
        RandomAccessFile out = null;
        try {
            out = new RandomAccessFile(favorPhrase, "rw");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("是否从上次读取的位置继续读取成语(输入y或n)");
        String answer = reader.nextLine();
        if (answer.startsWith("y")||answer.startsWith("Y")) {
            Caretaker caretaker = new Caretaker();   //创建负责人
            Memento memento = caretaker.getMemento(); //得到备忘录
            if (memento != null) {
                readPhrase.restoreFromMemento(memento);  //使用备忘录恢复状态
            }
            String phrase = null;
            while((phrase = readPhrase.readLine()) != null) {
                System.out.println(phrase);
                System.out.println("是否将该成语保存到" + favorPhrase.getName());
                answer = reader.nextLine();
                if (answer.startsWith("y")||answer.startsWith("Y")) {
                    try {
                        out.seek(favorPhrase.length());
                        byte[] b = phrase.getBytes();
                        out.write(b);
                        out.write(' ');
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("是否继续读取成语?(输入y或n)");
                answer = reader.nextLine();
                if (answer.startsWith("y")||answer.startsWith("Y")) {
                    continue;
                } else {
                    readPhrase.closeRead();
                    caretaker.saveMemento(readPhrase.createMemento());
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    System.exit(0);
                }
            }
            System.out.println("读完全部成语");
        }
        System.exit(0);
    }
}

备忘录模式的优点

  • 备忘录模式使用备忘录可以把原发者的内部状态保存起来,使只有很“亲密的”的对象可以访问备忘录中的数据。
  • 备忘录模式强调了类设计单一责任原则,即将状态的刻画和保存分开。

适用备忘录模式的情景

下列情况之一就可以考虑使用备忘录模式

  • 必须保存一个对象在某一时刻的全部或部分状态,以便在需要时恢复该对象先前的状态。
  • 一个对象不想通过提供public权限的,诸如getXXX()的方法让其他对象得到自己的内部状态。

注:如果备忘录需要存储大量的数据或非常频繁地创建备忘录,可能会导致非常大的存储开销。

下载源码请到

MyGitHub

时间: 2024-09-23 03:51:48

Java设计模式--备忘录模式的相关文章

PHP设计模式——备忘录模式

声明:本系列博客参考资料<大话设计模式>,作者程杰.                 备忘录模式又叫做快照模式或Token模式,在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.              UML类图:                              角色:                 1.发起人(GameRole):负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态.发

IOS设计模式-备忘录模式

内容大纲 如何存储记录 备忘录模式的基本原理 使用备忘录模式 优化存储方案 恢复UIView的状态 1.如何存储记录 在存储记录时,第一步我们需要用一把钥匙去打开一把锁.第二步,当我们打开锁之后就会有黑盒子,我们一开始还不知道里面有什么,所以是黑盒子. 1.存储记录的必要性 生活中,比如去超市购物有时候就需要在入口储物柜存放自己的包裹 2.记录的唯一标示 储物柜对应一把钥匙和号码标示. 3.存储记录与取出记录 ===========================================

设计模式之禅之设计模式-备忘录模式

<一:备忘录模式的定义        --->备忘录模式(Memento Pattern)提供了一种弥补真实世界缺陷的方法,让"后悔药"在程序的世界中真实可行        --->在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.        --->通俗地说,备忘录模式就是一个对象的备份模式,提供了一种程序数据的备份方法 二:备忘录模式的角色 ● Originator发起人角色      

21、Python与设计模式--备忘录模式

一.游戏进度保存 打过游戏的朋友一定知道,大多数游戏都有保存进度的功能,如果一局游戏下来,忘保存了进度,那么下次只能从上次进度点开始重新打了.一般情况下,保存进度是要存在可持久化存储器上,本例中先以保存在内存中来模拟实现该场景的情形.以模拟一个战斗角色为例.首先,创建游戏角色. class GameCharacter(): vitality = 0 attack = 0 defense = 0 def displayState(self): print 'Current Values:' pri

Java设计模式---Builder模式

之前想多写一些关于设计模式之类的东西,但是一直没写,主要是现在网上写这些的太多了,都懒的弄,反正我写这篇是写给自己做笔记的,我自己看,哼. 设计模式真的太重要了,不论是以后转学哪门语言,面向对象思想在这了,架构搭起来就会清晰些. 动手: 以前我们给model赋值的时候是这个样子的 Person person=new Person(); person.setAge(13); person.setId("33"); person.setName("薛之谦"); 这个是我

java设计模式-桥接模式(屌丝男学设计模式)

本文介绍设计模式中的桥接(Bridge)模式的概念,用法,以及实际应用中怎么样使用桥接模式进行开发. Bridge模式的概念 Bridge 模式是构造型的设计模式之一.Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任.它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展. Bridge模式的应用场景 面向对象的程序设计(OOP)里有类继承(子类继承父类)的

Java设计模式--模板方法模式

模板方法模式 定义一个操作中算法的骨架,而将一些步骤延迟到子类中.模板方法使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. Template Method Pattern Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorit

Java设计模式--外观模式

外观模式 为系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. Facade Pattern Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. 类图 模式的结构与使用 外观模式的结构中包两种角色.

Java设计模式--桥接模式

桥接模式(别名:柄体模式) 将抽象部分于它的实现部分分离,使它们都可以独立地变化. Bridge Pattern(Another Name:Handle-Body) Decouple an abstraction from its implementation so that the two can vary independently. 类图 模式的结构与使用 桥接模式的结构中包括四种角色. + 抽象(Abstraction):是一个抽象类,该抽象类含有Implementor声明的变量,即维护