《模式——工程化实现及扩展》(设计模式C# 版)《命令模式 Command》——“自我检验" 参考答案
转自:《模式——工程化实现及扩展》(设计模式C# 版)
http://www.cnblogs.com/callwangxiang/1、 项目中命令模式的“操作”内容经常存在嵌套的要求
例如:排序算法内部往往还涉及交换、移位等操作
请采用本章介绍的泛型委托命名模式定义排序操作,要求它支持针对如下接口的排序算法,并验证之。
要求:本示例纯粹为了练习嵌套命令模式的实现方式,请不要使用.NET内置的集合类型排序,也不要通过LINQ执行排序
interface IEntity
{
int Id { get; set; }
int Age { get; set; }
}
class Entity : IEntity
{
public int Id { get; set; }
public int Age { get; set; }
}
class EntityWithName : Entity
{
public string Name { get; set; }
}
{
int Id { get; set; }
int Age { get; set; }
}
class Entity : IEntity
{
public int Id { get; set; }
public int Age { get; set; }
}
class EntityWithName : Entity
{
public string Name { get; set; }
}
参考答案
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Command.Tests.Exercise
{
[TestClass]
public class HierarchyCommandExerciseFixture
{
interface IEntity
{
int Id { get; set; }
int Age { get; set; }
}
class Entity : IEntity
{
public int Id { get; set; }
public int Age { get; set; }
}
class EntityWithName : Entity
{
public string Name { get; set; }
}
/// <summary>
/// 外部排序命令对象抽象定义
/// </summary>
Action<
IEntity[], // 表示待排序数据
Action<IEntity[], int, int>, // 表示交换子命令对象抽象定义
Func<IEntity, IEntity, bool>> // 表示比较子命令对象抽象定义
sortHandler;
IEntity[] testData;
/// <summary>
/// 准备测试数据
/// </summary>
[TestInitialize]
public void Initialize()
{
testData = new IEntity[]
{
new Entity(){Id = 1, Age = 20},
new Entity(){Id=2, Age=18},
new Entity(){Id=5, Age=12},
new EntityWithName(){Id=4, Age=30},
new Entity(){Id=10, Age=13}
};
}
/// <summary>
/// 验证对于ID属性方法的排序
/// </summary>
[TestMethod]
public void TestSortById()
{
#region 定义外部排序命令对象
// 冒泡算法排序
sortHandler = (data, swapHandler, compareHandler) =>
{
if ((data == null) || (data.Length == 0)) throw new ArgumentNullException("data");
if (data.Length == 1) return;
for (var i = 0; i < data.Length - 1; i++)
{
for (var j = i + 1; j < data.Length; j++)
if (!compareHandler(data[i], data[j]))
swapHandler(data, i, j);
}
};
#endregion
#region 内部嵌套的命令对象
Action<IEntity[], int, int>
swap = (data, x, y) =>
{
var temp = data[x];
data[x] = data[y];
data[y] = temp;
};
// 先定义为倒序排列
Func<IEntity, IEntity, bool> compare = (x, y) => x.Id >= y.Id;
#endregion
// 验证倒序排列效果
sortHandler(testData, swap, compare);
Assert.IsNotNull(testData);
for (var i = 0; i < testData.Length - 1; i++)
Assert.IsTrue(testData[i].Id >= testData[i+1].Id);
// 修改内部命令对象的定义,采用升序排列
compare = (x, y) => x.Id <= y.Id;
// 重新定义整体的命令对象
sortHandler(testData, swap, compare);
// 验证升序排列效果
Assert.IsNotNull(testData);
for (var i = 0; i < testData.Length - 1; i++)
Assert.IsTrue(testData[i].Id <= testData[i + 1].Id);
}
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Command.Tests.Exercise
{
[TestClass]
public class HierarchyCommandExerciseFixture
{
interface IEntity
{
int Id { get; set; }
int Age { get; set; }
}
class Entity : IEntity
{
public int Id { get; set; }
public int Age { get; set; }
}
class EntityWithName : Entity
{
public string Name { get; set; }
}
/// <summary>
/// 外部排序命令对象抽象定义
/// </summary>
Action<
IEntity[], // 表示待排序数据
Action<IEntity[], int, int>, // 表示交换子命令对象抽象定义
Func<IEntity, IEntity, bool>> // 表示比较子命令对象抽象定义
sortHandler;
IEntity[] testData;
/// <summary>
/// 准备测试数据
/// </summary>
[TestInitialize]
public void Initialize()
{
testData = new IEntity[]
{
new Entity(){Id = 1, Age = 20},
new Entity(){Id=2, Age=18},
new Entity(){Id=5, Age=12},
new EntityWithName(){Id=4, Age=30},
new Entity(){Id=10, Age=13}
};
}
/// <summary>
/// 验证对于ID属性方法的排序
/// </summary>
[TestMethod]
public void TestSortById()
{
#region 定义外部排序命令对象
// 冒泡算法排序
sortHandler = (data, swapHandler, compareHandler) =>
{
if ((data == null) || (data.Length == 0)) throw new ArgumentNullException("data");
if (data.Length == 1) return;
for (var i = 0; i < data.Length - 1; i++)
{
for (var j = i + 1; j < data.Length; j++)
if (!compareHandler(data[i], data[j]))
swapHandler(data, i, j);
}
};
#endregion
#region 内部嵌套的命令对象
Action<IEntity[], int, int>
swap = (data, x, y) =>
{
var temp = data[x];
data[x] = data[y];
data[y] = temp;
};
// 先定义为倒序排列
Func<IEntity, IEntity, bool> compare = (x, y) => x.Id >= y.Id;
#endregion
// 验证倒序排列效果
sortHandler(testData, swap, compare);
Assert.IsNotNull(testData);
for (var i = 0; i < testData.Length - 1; i++)
Assert.IsTrue(testData[i].Id >= testData[i+1].Id);
// 修改内部命令对象的定义,采用升序排列
compare = (x, y) => x.Id <= y.Id;
// 重新定义整体的命令对象
sortHandler(testData, swap, compare);
// 验证升序排列效果
Assert.IsNotNull(testData);
for (var i = 0; i < testData.Length - 1; i++)
Assert.IsTrue(testData[i].Id <= testData[i + 1].Id);
}
}
}
2、 请实现一个队列化命令模式示例并验证
参考答案
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Command.Tests.Exercise
{
[TestClass]
public class QueuedCommandExerciseFixture
{
List<string> messages = new List<string>{"hello","command", "pattern"};
[TestMethod]
public void TestQueuedSerializedCommand()
{
// 定义保存命令对象的队列
// 命令对象的抽象形式为返回结果为string的空参数方法 Func<string>
var queue = new Queue<Func<string>>();
// 将命令对象入队列
messages.ForEach(x=>queue.Enqueue(() => x));
// 逐个验证出队列后各命令对象是否次序和执行功能正常
var i = 0;
while(queue.Count > 0)
{
var command = queue.Dequeue();
Trace.WriteLine(command());
Assert.AreEqual<string>(messages[i], command());
i++;
}
}
}
}
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Command.Tests.Exercise
{
[TestClass]
public class QueuedCommandExerciseFixture
{
List<string> messages = new List<string>{"hello","command", "pattern"};
[TestMethod]
public void TestQueuedSerializedCommand()
{
// 定义保存命令对象的队列
// 命令对象的抽象形式为返回结果为string的空参数方法 Func<string>
var queue = new Queue<Func<string>>();
// 将命令对象入队列
messages.ForEach(x=>queue.Enqueue(() => x));
// 逐个验证出队列后各命令对象是否次序和执行功能正常
var i = 0;
while(queue.Count > 0)
{
var command = queue.Dequeue();
Trace.WriteLine(command());
Assert.AreEqual<string>(messages[i], command());
i++;
}
}
}
}
3、 下列示例是Wiki上给出的命令模式示例,请充分利用C#语法特征重写其命令模式部分的执行逻辑,并通过单元测试验证
引自:http://en.wikipedia.org/wiki/Command_pattern
using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Command.Tests.Exercise
{
[TestClass]
public class RewriteWikiJavaCommandSampleExerciseFixture
{
class Light
{
public void TurnOn(){Trace.WriteLine("the light is on");}
public void TurnDown() { Trace.WriteLine("the light is off"); }
}
class Switch
{
public Action UpCommand { private get; set; }
public Action DownCommand { private get; set; }
public void FlipUp() {UpCommand(); }
public void FlipDown() { DownCommand(); }
}
/// <summary>
/// 验证执行过程
/// </summary>
[TestMethod]
public void Test()
{
var light = new Light();
var s = new Switch()
{
UpCommand = light.TurnOn,
DownCommand = light.TurnDown
};
s.FlipUp();
s.FlipDown();
}
}
}
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MarvellousWorks.PracticalPattern.Command.Tests.Exercise
{
[TestClass]
public class RewriteWikiJavaCommandSampleExerciseFixture
{
class Light
{
public void TurnOn(){Trace.WriteLine("the light is on");}
public void TurnDown() { Trace.WriteLine("the light is off"); }
}
class Switch
{
public Action UpCommand { private get; set; }
public Action DownCommand { private get; set; }
public void FlipUp() {UpCommand(); }
public void FlipDown() { DownCommand(); }
}
/// <summary>
/// 验证执行过程
/// </summary>
[TestMethod]
public void Test()
{
var light = new Light();
var s = new Switch()
{
UpCommand = light.TurnOn,
DownCommand = light.TurnDown
};
s.FlipUp();
s.FlipDown();
}
}
}
贸易电子化,技术全球化