1,
Analysis: from the description, although the calculation of inflation indicators is different, and the calculation process of each indicator is very complex, its algorithm structure is stable. Therefore, we should consider using a template-defined algorithm and hand over the calculation of specific indicators to the subclass for completion.
Template type
/// <Summary>
/// Template type
/// </Summary>
Abstract class InflationRateCalactorBase
{
# Contents implemented by region by subclass
Public abstract double LastYearIndicator {get ;}
Public abstract double ThisYearIndicator {get ;}
# Endregion
/// <Summary>
/// Algorithm Template
/// </Summary>
/// <Returns> </returns>
Public double GetInflationRate ()
{
Return (ThisYearIndicator-LastYearIndicator)/LastYearIndicator;
}
}
Subclass
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 ();}}
}
Unit Test
[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,
Define the template type and its external and internal template methods and algorithm templates
Interface IDocument {}
Class D1: IDocument {}
Class D2: IDocument {}
Class D3: IDocument {}
Class incluenteventargs <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>
/// The template method that you can see externally is a method void Process (T document) and an event EventHandler <DocumentEventArgs <T> DocumentSent
/// For subclass, the internal template is T ProcessInternal (T document) and Send (T document) methods.
/// The template of the entire algorithm is defined in void Process (T document ).
/// </Summary>
/// <Typeparam name = "T"> Object Type </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 algorithm Template
Trace. WriteLine (string. Format ("begin process document [{0}]", document. GetType (). Name ));
Document = ProcessInternal (document );
Send (document );
If (DocumentSent! = Null)
DocumentSent (this, new incluenteventargs <T> () {Document = document });
# Endregion
}
}
Unit Test
[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>
/// Event Response Template "fill"