对上面结构图的代码模拟:
package memento;
/**
*
*作者:alaric
*时间:2013-8-25下午2:04:27
*描述:备忘录角色
*/
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
package memento;
/**
*
*作者:alaric
*时间:2013-8-25下午2:48:32
*描述:发起人
*/
public class Originator {
private String state;
public Memento createMemento(){
return new Memento(state);
}
/**
*
*作者:alaric
*时间:2013-8-25下午4:05:39
*描述:还原
*/
public void restoreMemento(Memento memento){
this.state = memento.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
package memento;
/**
*
*作者:alaric
*时间:2013-8-25下午2:48:05
*描述:管理者
*/
public class Caretaker {
private Memento memento;
/**
*
*作者:alaric
*时间:2013-8-25下午3:47:18
*描述:取值
*/
public Memento retrieveMemento(){
return memento;
}
/**
*
*作者:alaric
*时间:2013-8-25下午4:05:01
*描述:设置
*/
public void saveMemento(Memento memento){
this.memento = memento;
}
}
package memento;
/**
*
*作者:alaric
*时间:2013-8-25下午2:03:49
*描述:测试类
*/
public class Client {
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
/**
*作者:alaric
*时间:2013-8-25下午2:03:43
*描述:
*/
public static void main(String[] args) {
//改变发起人的状态
o.setState("on");
//创建备忘录对象,并保持于管理保持
c.saveMemento(o.createMemento());
//改变发起人的状态
o.setState("off");
//还原状态
o.restoreMemento(c.retrieveMemento());
}
}
对于上述描述中,客户端语句o.createMemento()得到备忘录后,是可以直接获取备忘录中信息的,因为备忘录类没有提供窄接口,这样就破坏了原有的封装性。这种设计备忘录角色的内部所存状态对所有对象是公开的,所以叫做"白箱"实现。有白箱就有黑箱,“黑箱”的实现方式就是利用java双接口的方式来隔离不同的对象访问的。
对于备忘录来说实现双接口,给发起人(Originator)角色展现宽接口,给管理者管理者(Caretaker)提供窄接口。宽接口由Memento本身就可以展现,窄接口只是个标识接口,不提供任何操作的方法。接下来看看如何用双接口方式“ 黑箱”实现。
描述代码如下:
package memento.black;
/**
*
*作者:alaric
*时间:2013-8-25下午6:12:48
*描述:标识接口
*/
public interface IMemento {
}
package memento.black;
/**
*
*作者:alaric
*时间:2013-8-25下午2:48:32
*描述:发起人
*/
public class Originator {
private String state;
/**
*
*作者:alaric
*时间:2013-8-25下午6:18:36
*描述:穿件备忘录
*/
public IMemento createMemento(){
return (IMemento) new Memento(state);
}
/**
*
*作者:alaric
*时间:2013-8-25下午4:05:39
*描述:还原
*/
public void restoreMemento(IMemento memento){
Memento m = (Memento) memento;
setState(m.getState());
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
System.out.println("current state:"+state);
}
/**
*
*作者:alaric
*时间:2013-8-25下午9:22:02
*描述:内部类
*/
public class Memento implements IMemento{
private String state;
public Memento(String state){
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
}
package memento.black;
/**
*
*作者:alaric
*时间:2013-8-25下午2:48:05
*描述:管理者
*/
public class Caretaker {
private IMemento memento;
/**
*
*作者:alaric
*时间:2013-8-25下午3:47:18
*描述:取值
*/
public IMemento retrieveMemento(){
return memento;
}
/**
*
*作者:alaric
*时间:2013-8-25下午4:05:01
*描述:设值
*/
public void saveMemento(IMemento memento){
this.memento = memento;
}
}
package memento.black;
/**
*
*作者:alaric
*时间:2013-8-25下午2:03:49
*描述:测试类
*/
public class Client {
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
/**
*作者:alaric
*时间:2013-8-25下午2:03:43
*描述:
*/
public static void main(String[] args) {
//改变发起人的状态
o.setState("on");
//创建备忘录对象,并保持于管理保持
c.saveMemento(o.createMemento());
//改变发起人的状态
o.setState("off");
//还原状态
o.restoreMemento(c.retrieveMemento());
}
}
运行结果:
描述代码如下:
package memento.example;
/**
*
*作者:alaric
*时间:2013-8-25下午6:12:48
*描述:标识接口
*/
public interface IMemento {
}
package memento.example;
/**
*
*作者:alaric
*时间:2013-8-25下午2:48:32
*描述:数据库系统(发起人角色)
*/
public class DatabaseServer {
private boolean isUseable;
/**
*
*作者:alaric
*时间:2013-8-25下午6:18:36
*描述:穿件备忘录
*/
public IMemento createMemento(){
return (IMemento) new Memento(isUseable);
}
/**
*
*作者:alaric
*时间:2013-8-25下午4:05:39
*描述:还原
*/
public boolean restoreMemento(IMemento memento){
Memento m = (Memento) memento;
setUseable(m.isUseable());
return this.isUseable;
}
public boolean isUseable() {
return isUseable;
}
public void setUseable(boolean isUseable) {
this.isUseable = isUseable;
System.out.println("DB state useable is: "+isUseable);
}
/**
*
*作者:alaric
*时间:2013-8-25下午9:22:02
*描述:内部类
*/
public class Memento implements IMemento{
private boolean isUseable;
public Memento(boolean isUseable) {
super();
this.isUseable = isUseable;
}
public boolean isUseable() {
return isUseable;
}
public void setUseable(boolean isUseable) {
this.isUseable = isUseable;
}
}
}
package memento.example;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
*作者:alaric
*时间:2013-8-25下午2:48:05
*描述:备份服务器(管理者)
*/
public class BackupsServer {
private DatabaseServer dbServer ;//增强管理者的功能,把发起人的操作放在这里
private Map<Long,IMemento> mementos ;//用一个map来对数据库服务多点备份
public BackupsServer(DatabaseServer dbServer) {
super();
this.dbServer = dbServer;
mementos = new ConcurrentHashMap<>();
}
/**
*
*作者:alaric
*时间:2013-8-25下午3:47:18
*描述:还原
*/
public void retrieveMemento(){
Iterator<Long> it = mementos.keySet().iterator();
//还原到最近一个可用的状态
while(it.hasNext()){
Long key = it.next();
IMemento val = mementos.get(key);
boolean isUseable = dbServer.restoreMemento(val);
if(isUseable){
break;
}
}
}
/**
*
*作者:alaric
*时间:2013-8-25下午4:05:01
*描述:备份
*/
public void createMemento(){
IMemento memento = dbServer.createMemento();
this.mementos.put(new Date().getTime(), memento);
}
}
package memento.example;
import java.util.Map;
import memento.Caretaker;
/**
*
*作者:alaric
*时间:2013-8-25下午2:03:49
*描述:测试类
*/
public class Client {
private static DatabaseServer dbServer = new DatabaseServer();
private static BackupsServer backupServer = new BackupsServer(dbServer);
/**
*作者:alaric
*时间:2013-8-25下午2:03:43
*描述:
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
//数据库系统设置可用状态
dbServer.setUseable(true);
//备份
backupServer.createMemento();
//1秒钟备份一次
Thread.sleep(1000);
dbServer.setUseable(true);
backupServer.createMemento();
Thread.sleep(1000);
dbServer.setUseable(true);
backupServer.createMemento();
Thread.sleep(1000);
//设置系统故障
dbServer.setUseable(false);
//系统故障立即还原到最近一次可用状态
System.out.println("------系统还原-----");
backupServer.retrieveMemento();
}
}
运行结果: