《模式——工程化实现及扩展》(设计模式C# 版)《备忘录模式 Memento》——“自我检验" 参考答案
转自:《模式——工程化实现及扩展》(设计模式C# 版)
http://www.cnblogs.com/callwangxiang/
1、
interface IOriginator<T>
where T : IState
{
/// <summary>
/// 保存一个备忘
/// </summary>
/// <remarks>
/// 默认方式——当前所有数据的全备忘
/// </remarks>
void SaveCheckPoint();
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <remarks>
/// 默认方式——恢复最近一次全备忘
/// </remarks>
void Undo();
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
void SaveCheckPoint(string name);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
void Undo(string name);
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
void SaveCheckPoint(string name, string version);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
void Undo(string name, string version);
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
void SaveCheckPoint(string name, string version, string subjectName);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
void Undo(string name, string version, string subjectName);
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
/// <param name="start">时间区间起点</param>
/// <param name="end">时间区间终点</param>
void SaveCheckPoint(string name, string version, string subjectName, DateTime start, DateTime end);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
/// <param name="start">时间区间起点</param>
/// <param name="end">时间区间终点</param>
void Undo(string name, string version, string subjectName, DateTime start, DateTime end);
}
where T : IState
{
/// <summary>
/// 保存一个备忘
/// </summary>
/// <remarks>
/// 默认方式——当前所有数据的全备忘
/// </remarks>
void SaveCheckPoint();
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <remarks>
/// 默认方式——恢复最近一次全备忘
/// </remarks>
void Undo();
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
void SaveCheckPoint(string name);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
void Undo(string name);
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
void SaveCheckPoint(string name, string version);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
void Undo(string name, string version);
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
void SaveCheckPoint(string name, string version, string subjectName);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
void Undo(string name, string version, string subjectName);
/// <summary>
/// 保存一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
/// <param name="start">时间区间起点</param>
/// <param name="end">时间区间终点</param>
void SaveCheckPoint(string name, string version, string subjectName, DateTime start, DateTime end);
/// <summary>
/// 恢复一个备忘
/// </summary>
/// <param name="name">备忘的名称</param>
/// <param name="version">备忘的版本</param>
/// <param name="subjectName">业务主题名称</param>
/// <param name="start">时间区间起点</param>
/// <param name="end">时间区间终点</param>
void Undo(string name, string version, string subjectName, DateTime start, DateTime end);
}
2、集成Memento和CoR
示例说明:
1) 为了简化示例,用string替换IState 接口
2)CoR没有采用链表方式,而是通过LINQ方式实现
3) CoR中的每个Handler设计为具有闭合操作的接口(压缩、签名、加密等,在恢复的时候还需要进行对应的反向处理)
4)在SaveCheckPoint()和Undo()的过程中分别调用CoR的正向处理和反向处理
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Memento.Tests.Exercise
{
[TestClass]
public class MementoCoRFixture
{
/// <summary>
/// 为了简化没有定义原发器接口,直接定义了原发器类型
/// </summary>
class Originator
{
public string State { get; set; }
Memento m;
public HandlerCoRBuilder<string> HandlerCoRBuilder { get; set; }
/// <summary>
/// 把备忘录定义为原发器的内部类型
/// </summary>
/// <typeparam name="T"></typeparam>
class Memento
{
public string State { get; set; }
}
/// <summary>
/// 把状态保存到备忘录
/// </summary>
public virtual void SaveCheckpoint()
{
Trace.WriteLine("\nOriginator.void SaveCheckpoint()\n-----------------");
m = new Memento()
{
State = ProcessState(HandlerCoRBuilder.BuildUpProcessCoR(), this.State)
};
}
/// <summary>
/// 从备忘录恢复之前的状态
/// </summary>
public virtual void Undo()
{
if (m == null) return;
Trace.WriteLine("\nOriginator.void Undo()\n-----------------");
State = ProcessState(HandlerCoRBuilder.BuildUpReverseCoR(), m.State);
}
string ProcessState(IEnumerable<Func<string, string >> processes, string state)
{
if(string.IsNullOrEmpty(state)) throw new ArgumentNullException("state");
if(processes == null) return state;
foreach (var process in processes)
state = process(state);
return state;
}
}
class HandlerCoRBuilder<T>
{
public HandlerCoRBuilder() { Handlers = new List<HandlerBase<T>>(); }
public IList<HandlerBase<T>> Handlers { get; private set; }
public IEnumerable<Func<T, T>> BuildUpProcessCoR()
{
if ((Handlers == null) || (Handlers.Count == 0)) return null;
return Handlers.OrderBy(x => x.Sequence).Select(x => new Func<T, T>(x.Process));
}
public IEnumerable<Func<T, T>> BuildUpReverseCoR()
{
if ((Handlers == null) || (Handlers.Count == 0)) return null;
return Handlers.OrderByDescending(x => x.Sequence).Select(x => new Func<T, T>(x.Reverse));
}
}
/// <summary>
/// 为了简化,假设State为string
/// </summary>
abstract class HandlerBase<T>
{
/// <summary>
/// 操作执行的序列
/// </summary>
public int Sequence { get; set; }
/// <summary>
/// 正向操作内容
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public abstract T Process(T target);
/// <summary>
/// 逆向操作内容
/// </summary>
/// <param name="tareget"></param>
/// <returns></returns>
public abstract T Reverse(T tareget);
}
static Func<string, string, string> mementoProcessHandler =
(x, y) =>
{
var result = string.Format("<{0}>{1}</{2}>", y, x, y);
Trace.WriteLine(string.Format("{0} => {1}", x, result));
return result;
};
static Func<string, string, string> mementoReverseHandler =
(x, y) =>
{
var result = x.Replace("<" + y + ">", "").Replace("</" + y + ">", "");
Trace.WriteLine(string.Format("{0} => {1}", x, result));
return result;
};
class CompressHandler : HandlerBase<string>
{
public override string Process(string target) { return mementoProcessHandler(target, "c"); }
public override string Reverse(string tareget) { return mementoReverseHandler(tareget, "c"); }
}
class EncryptHandler : HandlerBase<string>
{
public override string Process(string target) { return mementoProcessHandler(target, "e"); }
public override string Reverse(string tareget) { return mementoReverseHandler(tareget, "e"); }
}
class SignHandler : HandlerBase<string>
{
public override string Process(string target) { return mementoProcessHandler(target, "s"); }
public override string Reverse(string tareget) { return mementoReverseHandler(tareget, "s"); }
}
Originator originator;
HandlerCoRBuilder<string> builder;
[TestInitialize]
public void Initialize()
{
builder = new HandlerCoRBuilder<string>();
builder.Handlers.Add(new CompressHandler(){Sequence = 2});
builder.Handlers.Add(new EncryptHandler() { Sequence = 3 });
builder.Handlers.Add(new SignHandler() { Sequence = 1 });
originator = new Originator()
{
HandlerCoRBuilder = builder
};
}
[TestMethod]
public void TestMementoAndCoRIntegration()
{
originator.State = "hello";
originator.SaveCheckpoint();
originator.State = "world";
originator.Undo();
Assert.AreEqual<string>("hello", originator.State);
}
}
}
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Memento.Tests.Exercise
{
[TestClass]
public class MementoCoRFixture
{
/// <summary>
/// 为了简化没有定义原发器接口,直接定义了原发器类型
/// </summary>
class Originator
{
public string State { get; set; }
Memento m;
public HandlerCoRBuilder<string> HandlerCoRBuilder { get; set; }
/// <summary>
/// 把备忘录定义为原发器的内部类型
/// </summary>
/// <typeparam name="T"></typeparam>
class Memento
{
public string State { get; set; }
}
/// <summary>
/// 把状态保存到备忘录
/// </summary>
public virtual void SaveCheckpoint()
{
Trace.WriteLine("\nOriginator.void SaveCheckpoint()\n-----------------");
m = new Memento()
{
State = ProcessState(HandlerCoRBuilder.BuildUpProcessCoR(), this.State)
};
}
/// <summary>
/// 从备忘录恢复之前的状态
/// </summary>
public virtual void Undo()
{
if (m == null) return;
Trace.WriteLine("\nOriginator.void Undo()\n-----------------");
State = ProcessState(HandlerCoRBuilder.BuildUpReverseCoR(), m.State);
}
string ProcessState(IEnumerable<Func<string, string >> processes, string state)
{
if(string.IsNullOrEmpty(state)) throw new ArgumentNullException("state");
if(processes == null) return state;
foreach (var process in processes)
state = process(state);
return state;
}
}
class HandlerCoRBuilder<T>
{
public HandlerCoRBuilder() { Handlers = new List<HandlerBase<T>>(); }
public IList<HandlerBase<T>> Handlers { get; private set; }
public IEnumerable<Func<T, T>> BuildUpProcessCoR()
{
if ((Handlers == null) || (Handlers.Count == 0)) return null;
return Handlers.OrderBy(x => x.Sequence).Select(x => new Func<T, T>(x.Process));
}
public IEnumerable<Func<T, T>> BuildUpReverseCoR()
{
if ((Handlers == null) || (Handlers.Count == 0)) return null;
return Handlers.OrderByDescending(x => x.Sequence).Select(x => new Func<T, T>(x.Reverse));
}
}
/// <summary>
/// 为了简化,假设State为string
/// </summary>
abstract class HandlerBase<T>
{
/// <summary>
/// 操作执行的序列
/// </summary>
public int Sequence { get; set; }
/// <summary>
/// 正向操作内容
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public abstract T Process(T target);
/// <summary>
/// 逆向操作内容
/// </summary>
/// <param name="tareget"></param>
/// <returns></returns>
public abstract T Reverse(T tareget);
}
static Func<string, string, string> mementoProcessHandler =
(x, y) =>
{
var result = string.Format("<{0}>{1}</{2}>", y, x, y);
Trace.WriteLine(string.Format("{0} => {1}", x, result));
return result;
};
static Func<string, string, string> mementoReverseHandler =
(x, y) =>
{
var result = x.Replace("<" + y + ">", "").Replace("</" + y + ">", "");
Trace.WriteLine(string.Format("{0} => {1}", x, result));
return result;
};
class CompressHandler : HandlerBase<string>
{
public override string Process(string target) { return mementoProcessHandler(target, "c"); }
public override string Reverse(string tareget) { return mementoReverseHandler(tareget, "c"); }
}
class EncryptHandler : HandlerBase<string>
{
public override string Process(string target) { return mementoProcessHandler(target, "e"); }
public override string Reverse(string tareget) { return mementoReverseHandler(tareget, "e"); }
}
class SignHandler : HandlerBase<string>
{
public override string Process(string target) { return mementoProcessHandler(target, "s"); }
public override string Reverse(string tareget) { return mementoReverseHandler(tareget, "s"); }
}
Originator originator;
HandlerCoRBuilder<string> builder;
[TestInitialize]
public void Initialize()
{
builder = new HandlerCoRBuilder<string>();
builder.Handlers.Add(new CompressHandler(){Sequence = 2});
builder.Handlers.Add(new EncryptHandler() { Sequence = 3 });
builder.Handlers.Add(new SignHandler() { Sequence = 1 });
originator = new Originator()
{
HandlerCoRBuilder = builder
};
}
[TestMethod]
public void TestMementoAndCoRIntegration()
{
originator.State = "hello";
originator.SaveCheckpoint();
originator.State = "world";
originator.Undo();
Assert.AreEqual<string>("hello", originator.State);
}
}
}
Output窗口
验证可以在备忘/恢复过程中同时通过CoR对于备忘信息进行“一系列”处理
------ Test started: Assembly: Memento.Tests.dll ------
Originator.void SaveCheckpoint()
-----------------
hello => <s>hello</s>
<s>hello</s> => <c><s>hello</s></c>
<c><s>hello</s></c> => <e><c><s>hello</s></c></e>
Originator.void Undo()
-----------------
<e><c><s>hello</s></c></e> => <c><s>hello</s></c>
<c><s>hello</s></c> => <s>hello</s>
<s>hello</s> => hello
1 passed, 0 failed, 0 skipped, took 0.67 seconds (MSTest 10.0).
Originator.void SaveCheckpoint()
-----------------
hello => <s>hello</s>
<s>hello</s> => <c><s>hello</s></c>
<c><s>hello</s></c> => <e><c><s>hello</s></c></e>
Originator.void Undo()
-----------------
<e><c><s>hello</s></c></e> => <c><s>hello</s></c>
<c><s>hello</s></c> => <s>hello</s>
<s>hello</s> => hello
1 passed, 0 failed, 0 skipped, took 0.67 seconds (MSTest 10.0).
3、
设计要点:
1) 为备忘信息接口增加优先级属性方法
2)增加IMementoStore接口抽象不同的存储对象
3)通过集成策略模式实现备忘记录和备忘存储的匹配关系
贸易电子化,技术全球化