《模式——工程化实现及扩展》(设计模式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);
}

 

 

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 { getset; }

            Memento m;

            
public HandlerCoRBuilder<string> HandlerCoRBuilder { getset; }

            
/// <summary>
            
/// 把备忘录定义为原发器的内部类型
            
/// </summary>
            
/// <typeparam name="T"></typeparam>
            class Memento
            {
                
public string State { getset; }
            }

            
/// <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 == nullreturn;
                Trace.WriteLine(
"\nOriginator.void Undo()\n-----------------");
                State 
= ProcessState(HandlerCoRBuilder.BuildUpReverseCoR(), m.State);
            }

            
string ProcessState(IEnumerable<Func<stringstring >> processes, string state)
            {
                
if(string.IsNullOrEmpty(state)) throw new ArgumentNullException("state");
                
if(processes == nullreturn 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 { getprivate 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 { getset; }

            
/// <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<stringstringstring> 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<stringstringstring> 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).

 

 3、

设计要点:

1) 为备忘信息接口增加优先级属性方法

2)增加IMementoStore接口抽象不同的存储对象

3)通过集成策略模式实现备忘记录和备忘存储的匹配关系

 

 

 

 

 

 

posted @ 2011-05-25 14:09  蜡笔小王  阅读(1405)  评论(0编辑  收藏  举报