《模式——工程化实现及扩展》(设计模式C# 版)《模板方法模式 Template》——“自我检验" 参考答案
转自:《模式——工程化实现及扩展》(设计模式C# 版)
http://www.cnblogs.com/callwangxiang/
http://www.cnblogs.com/callwangxiang/archive/2011/05/20/ExerciseAATemplate.html的参考答案
1、
分析:从描述看,尽管计算通胀的指标不同,而且每个指标的计算过程都很复杂,但其算法结构稳定。因此,考虑将采用模板定义算法,而将具体指标的计算交给子类完成
模板类型
/// <summary>
/// 模板类型
/// </summary>
abstract class InflationRateCalactorBase
{
#region 交由子类实现的内容
public abstract double LastYearIndicator{get;}
public abstract double ThisYearIndicator { get;}
#endregion
/// <summary>
/// 算法模板
/// </summary>
/// <returns></returns>
public double GetInflationRate()
{
return (ThisYearIndicator - LastYearIndicator)/LastYearIndicator;
}
}
/// 模板类型
/// </summary>
abstract class InflationRateCalactorBase
{
#region 交由子类实现的内容
public abstract double LastYearIndicator{get;}
public abstract double ThisYearIndicator { get;}
#endregion
/// <summary>
/// 算法模板
/// </summary>
/// <returns></returns>
public double GetInflationRate()
{
return (ThisYearIndicator - LastYearIndicator)/LastYearIndicator;
}
}
子类
class GdpInflationRateCalactor : InflationRateCalactorBase
{
public override double LastYearIndicator { get { throw new NotImplementedException(); } }
public override double ThisYearIndicator { get { throw new NotImplementedException(); } }
}
class CpiInflationRateCalactor : InflationRateCalactorBase
{
public override double LastYearIndicator { get { throw new NotImplementedException(); } }
public override double ThisYearIndicator { get { throw new NotImplementedException(); } }
}
class PpiInflationRateCalactor : InflationRateCalactorBase
{
public override double LastYearIndicator { get { throw new NotImplementedException(); } }
public override double ThisYearIndicator { get { throw new NotImplementedException(); } }
}
{
public override double LastYearIndicator { get { throw new NotImplementedException(); } }
public override double ThisYearIndicator { get { throw new NotImplementedException(); } }
}
class CpiInflationRateCalactor : InflationRateCalactorBase
{
public override double LastYearIndicator { get { throw new NotImplementedException(); } }
public override double ThisYearIndicator { get { throw new NotImplementedException(); } }
}
class PpiInflationRateCalactor : InflationRateCalactorBase
{
public override double LastYearIndicator { get { throw new NotImplementedException(); } }
public override double ThisYearIndicator { get { throw new NotImplementedException(); } }
}
单元测试
[TestClass]
public class InflationRateFixture
{
InflationRateCalactorBase c1;
InflationRateCalactorBase c2;
InflationRateCalactorBase c3;
[TestInitialize]
public void Initialize()
{
c1 = new GdpInflationRateCalactor();
c2 = new CpiInflationRateCalactor();
c3 = new PpiInflationRateCalactor();
}
[TestMethod]
public void TestInflationRateCalculatorTemplate()
{
ExecuteInflationRateCalactor(c1);
ExecuteInflationRateCalactor(c2);
ExecuteInflationRateCalactor(c3);
}
void ExecuteInflationRateCalactor(InflationRateCalactorBase calculator)
{
if (calculator == null) throw new ArgumentNullException("calculator");
try
{
calculator.GetInflationRate();
}
catch(NotImplementedException){}
}
}
public class InflationRateFixture
{
InflationRateCalactorBase c1;
InflationRateCalactorBase c2;
InflationRateCalactorBase c3;
[TestInitialize]
public void Initialize()
{
c1 = new GdpInflationRateCalactor();
c2 = new CpiInflationRateCalactor();
c3 = new PpiInflationRateCalactor();
}
[TestMethod]
public void TestInflationRateCalculatorTemplate()
{
ExecuteInflationRateCalactor(c1);
ExecuteInflationRateCalactor(c2);
ExecuteInflationRateCalactor(c3);
}
void ExecuteInflationRateCalactor(InflationRateCalactorBase calculator)
{
if (calculator == null) throw new ArgumentNullException("calculator");
try
{
calculator.GetInflationRate();
}
catch(NotImplementedException){}
}
}
2、
定义模板类型及其对外、对内的模板方法以及算法模板
interface IDocument { }
class D1 : IDocument { }
class D2 : IDocument { }
class D3 : IDocument { }
class DocumentEventArgs<T> : EventArgs
where T : IDocument
{
public T Document { get; set; }
}
interface IDocumentBroker<T>
where T : IDocument
{
void Process(T document);
event EventHandler<DocumentEventArgs<T>> DocumentSent;
}
/// <summary>
/// 对外部看到的模板方法是一个方法void Process(T document)和一个事件event EventHandler<DocumentEventArgs<T>> DocumentSent
/// 对于子类而言,内部模板是T ProcessInternal(T document)和 Send(T document)两个方法
/// 而整个算法的模板定义在void Process(T document)中
/// </summary>
/// <typeparam name="T">文件实体类型</typeparam>
abstract class DocumentBrokerBase<T> : IDocumentBroker<T>
where T : IDocument
{
public event EventHandler<DocumentEventArgs<T>> DocumentSent;
protected abstract void Send(T document);
protected abstract T ProcessInternal(T document);
public virtual void Process(T document)
{
if (document == null) throw new ArgumentNullException("document");
#region 算法的模板
Trace.WriteLine(string.Format("begin process document [{0}]", document.GetType().Name));
document = ProcessInternal(document);
Send(document);
if (DocumentSent != null)
DocumentSent(this, new DocumentEventArgs<T>() { Document = document });
#endregion
}
}
class D1 : IDocument { }
class D2 : IDocument { }
class D3 : IDocument { }
class DocumentEventArgs<T> : EventArgs
where T : IDocument
{
public T Document { get; set; }
}
interface IDocumentBroker<T>
where T : IDocument
{
void Process(T document);
event EventHandler<DocumentEventArgs<T>> DocumentSent;
}
/// <summary>
/// 对外部看到的模板方法是一个方法void Process(T document)和一个事件event EventHandler<DocumentEventArgs<T>> DocumentSent
/// 对于子类而言,内部模板是T ProcessInternal(T document)和 Send(T document)两个方法
/// 而整个算法的模板定义在void Process(T document)中
/// </summary>
/// <typeparam name="T">文件实体类型</typeparam>
abstract class DocumentBrokerBase<T> : IDocumentBroker<T>
where T : IDocument
{
public event EventHandler<DocumentEventArgs<T>> DocumentSent;
protected abstract void Send(T document);
protected abstract T ProcessInternal(T document);
public virtual void Process(T document)
{
if (document == null) throw new ArgumentNullException("document");
#region 算法的模板
Trace.WriteLine(string.Format("begin process document [{0}]", document.GetType().Name));
document = ProcessInternal(document);
Send(document);
if (DocumentSent != null)
DocumentSent(this, new DocumentEventArgs<T>() { Document = document });
#endregion
}
}
单元测试
[TestClass]
public class DocumentBrokerFixture
{
IFactory factory;
[TestInitialize]
public void Initialize()
{
factory = new Factory()
.RegisterType<IDocumentBroker<D1>, D1DocumentBroker>()
.RegisterType<IDocumentBroker<D2>, D2DocumentBroker>()
.RegisterType<IDocumentBroker<D3>, D3DocumentBroker>();
}
[TestMethod]
public void TestD1Broker()
{
var broker = factory.Create<IDocumentBroker<D1>>();
broker.DocumentSent += OnDocumentSent<D1>;
broker.Process(new D1());
}
[TestMethod]
public void TestD2Broker()
{
var broker = factory.Create<IDocumentBroker<D2>>();
broker.DocumentSent += OnDocumentSent<D2>;
broker.Process(new D2());
}
[TestMethod]
public void TestD3Broker()
{
var broker = factory.Create<IDocumentBroker<D3>>();
broker.DocumentSent += OnDocumentSent<D3>;
broker.DocumentSent += OnDocumentCrossPlatformSent<D3>;
broker.Process(new D3());
}
/// <summary>
/// 响应事件方式的模板“填充”内容
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
void OnDocumentSent<T>(object sender, DocumentEventArgs<T> eventArgs)
where T : IDocument
{
Trace.WriteLine(string.Format("docuemnt [{0}] has been sent by {1}",
eventArgs.Document.GetType().Name,
sender.GetType().Name));
}
/// <summary>
/// 响应事件方式的模板“填充”内容
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
void OnDocumentCrossPlatformSent<T>(object sender, DocumentEventArgs<T> eventArgs)
where T : IDocument
{
Trace.WriteLine("cross platform communication");
}
}
public class DocumentBrokerFixture
{
IFactory factory;
[TestInitialize]
public void Initialize()
{
factory = new Factory()
.RegisterType<IDocumentBroker<D1>, D1DocumentBroker>()
.RegisterType<IDocumentBroker<D2>, D2DocumentBroker>()
.RegisterType<IDocumentBroker<D3>, D3DocumentBroker>();
}
[TestMethod]
public void TestD1Broker()
{
var broker = factory.Create<IDocumentBroker<D1>>();
broker.DocumentSent += OnDocumentSent<D1>;
broker.Process(new D1());
}
[TestMethod]
public void TestD2Broker()
{
var broker = factory.Create<IDocumentBroker<D2>>();
broker.DocumentSent += OnDocumentSent<D2>;
broker.Process(new D2());
}
[TestMethod]
public void TestD3Broker()
{
var broker = factory.Create<IDocumentBroker<D3>>();
broker.DocumentSent += OnDocumentSent<D3>;
broker.DocumentSent += OnDocumentCrossPlatformSent<D3>;
broker.Process(new D3());
}
/// <summary>
/// 响应事件方式的模板“填充”内容
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
void OnDocumentSent<T>(object sender, DocumentEventArgs<T> eventArgs)
where T : IDocument
{
Trace.WriteLine(string.Format("docuemnt [{0}] has been sent by {1}",
eventArgs.Document.GetType().Name,
sender.GetType().Name));
}
/// <summary>
/// 响应事件方式的模板“填充”内容
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
void OnDocumentCrossPlatformSent<T>(object sender, DocumentEventArgs<T> eventArgs)
where T : IDocument
{
Trace.WriteLine("cross platform communication");
}
}
贸易电子化,技术全球化