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 == 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
}
}
單元測試
[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>
/// 響應事件方式的模板“填充”