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

 

子类

复制代码
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(); } }
}
复制代码

 

单元测试

 

复制代码
[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 == nullthrow 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 { getset; }
}

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 == nullthrow new ArgumentNullException("document");

        
#region 算法的模板

        Trace.WriteLine(
string.Format("begin process document [{0}]", document.GetType().Name));
        document 
= ProcessInternal(document);

        Send(document);
        
if (DocumentSent != null)
            DocumentSent(
thisnew 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");
    }

}
复制代码

 

posted @   蜡笔小王  阅读(1281)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
历史上的今天:
2010-05-21 黑客软件设计的3条准则
点击右上角即可分享
微信分享提示