私にとって、進むべき道はインターフェースとファクトリーでしょう。さまざまなクラスが非表示にできるインターフェースへの参照を返すもの。実際の不快な作業を行うクラスはすべて、ファクトリに登録する必要があります。これにより、一連のパラメータを指定してインスタンス化するクラスがわかります。
注:インターフェースの代わりに抽象基本クラスを使用することもできますが、欠点は、単一継承言語の場合、単一の基本クラスに制限されることです。
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の実装者次第です。