对我来说,要走的路是接口和工厂。一种返回对接口的引用,各种类可以在其后隐藏。进行实际grunt工作的类都需要向Factory注册,以便它在给定一组参数的情况下知道要实例化哪个类。
注意:除了接口之外,您还可以使用抽象基类,但是缺点是对于单一继承语言,它会将您限制为一个基类。
TRepresentationType = (rtImage, rtTable, rtGraph, ...);
Factory.RegisterReader(TJSONReader, 'json');
Factory.RegisterReader(TXMLReader, 'xml');
Factory.RegisterWriter(TPDFWriter, 'pdf');
Factory.RegisterWriter(TPowerPointWriter, 'ppt');
Factory.RegisterWriter(TWordWriter, 'doc');
Factory.RegisterWriter(TWordWriter, 'docx');
Factory.RegisterRepresentation(TPNGImage, rtImage, 'png');
Factory.RegisterRepresentation(TGIFImage, rtImage, 'gif');
Factory.RegisterRepresentation(TJPGImage, rtImage, 'jpg');
Factory.RegisterRepresentation(TCsvTable, rtTable, 'csv');
Factory.RegisterRepresentation(THTMLTable, rtTable, 'html');
Factory.RegisterRepresentation(TBarChart, rtTGraph, 'bar');
Factory.RegisterRepresentation(TPieChart, rtTGraph, 'pie');
代码采用Delphi(Pascal)语法,因为这是我最熟悉的语言。
在工厂中注册了所有实现类之后,您应该能够请求对此类实例的接口引用。例如:
Factory.GetReader('SomeFileName.xml');
Factory.GetWriter('SomeExportFileName.ppt');
Factory.GetRepresentation(rtTable, 'html');
应该返回对TXMLReader实例的IReader引用;一个对TPowerPointWriter实例的IWriter引用和对THTMLTable实例的IRepresentation引用。
现在,渲染引擎需要做的就是将所有内容捆绑在一起:
procedure Render(
aDataFile: string;
aExportFile: string;
aRepresentationType: TRepresentationType;
aFormat: string;
);
var
Reader: IReader;
Writer: IWriter;
Representation: IRepresentation;
begin
Reader := Factory.GetReaderFor(aDataFile);
Writer := Factory.GetWriterFor(aExportFile);
Representation := Factory.GetRepresentationFor(aRepresentationType, aFormat);
Representation.ConstructFrom(Reader);
Writer.SaveToFile(Representation);
end;
IReader接口应该提供读取IRepresentation实现者构造数据表示形式所需的数据的方法。同样,IRepresentation应该提供IWriter实现者将数据表示形式导出为请求的导出文件格式所需的方法。
假设文件中的数据本质上是表格格式的,则IReader及其支持界面可能类似于:
IReader = interface(IInterface)
function MoveNext: Boolean;
function GetCurrent: IRow;
end;
IRow = interface(IInterface)
function MoveNext: Boolean;
function GetCurrent: ICol;
end;
ICol = interface(IInterface)
function GetName: string;
function GetValue: Variant;
end;
遍历一个表将是一个问题
while Reader.MoveNext do
begin
Row := Reader.GetCurrent;
while Row.MoveNext do
begin
Col := Row.GetCurrent;
// Do something with the column's name or value
end;
end;
由于表示形式本质上可以是图像,图形和文本,因此IRepresentation可能具有与IReader类似的方法来遍历构造的表,并且它将具有获取图像和图形的方法,例如以字节流的形式。IWriter实现者将根据导出目标的要求对表值和图像/图形字节进行编码。