《模式——工程化实现及扩展》(设计模式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 @ 2011-05-21 12:09  蜡笔小王  阅读(1266)  评论(0编辑  收藏  举报