Đối với tôi, con đường để đi sẽ là các giao diện và một Nhà máy. Một lớp trả về các tham chiếu đến các giao diện phía sau mà các lớp khác nhau có thể ẩn. Tất cả các lớp thực hiện công việc grunt thực tế đều cần phải được đăng ký với Factory để nó biết lớp nào sẽ khởi tạo một tập các tham số.
Lưu ý: thay vì các giao diện, bạn cũng có thể sử dụng các lớp cơ sở trừu tượng, nhưng nhược điểm là đối với các ngôn ngữ kế thừa duy nhất, nó giới hạn bạn trong một lớp cơ sở duy nhất.
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');
Mã nằm trong cú pháp Delphi (Pascal) vì đó là ngôn ngữ mà tôi quen thuộc nhất.
Sau khi tất cả các lớp thực hiện được đăng ký với nhà máy, bạn sẽ có thể yêu cầu một tham chiếu giao diện đến một thể hiện của một lớp như vậy. Ví dụ:
Factory.GetReader('SomeFileName.xml');
Factory.GetWriter('SomeExportFileName.ppt');
Factory.GetRepresentation(rtTable, 'html');
sẽ trả về một tham chiếu IReader cho một thể hiện của TXMLReader; một tham chiếu IWriter cho một thể hiện của TPowerPointWriter và một tham chiếu IRepftimeation đến một thể hiện của THTMLTable.
Bây giờ tất cả các công cụ kết xuất cần làm, là gắn kết mọi thứ lại với nhau:
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;
Giao diện IReader sẽ cung cấp các phương thức để đọc dữ liệu cần thiết bởi những người triển khai IRepftimeation để xây dựng biểu diễn dữ liệu. Tương tự IRepftimeation nên cung cấp các phương thức mà người triển khai IWriter cần xuất biểu diễn dữ liệu sang định dạng tệp xuất được yêu cầu.
Giả sử dữ liệu trong các tệp của bạn là dạng bảng, IReader và các giao diện hỗ trợ của nó có thể trông giống như:
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;
Lặp lại trên một bảng sau đó sẽ là một vấn đề của
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;
Vì các biểu diễn có thể là hình ảnh, đồ thị và văn bản trong tự nhiên, IRepftimeation có thể có các phương thức tương tự như IReader để duyệt qua một bảng được xây dựng và nó sẽ có các phương thức để lấy hình ảnh và đồ thị, ví dụ như một luồng byte. Nó sẽ tùy thuộc vào những người triển khai IWriter để mã hóa các giá trị bảng và các byte hình ảnh / đồ thị theo yêu cầu của mục tiêu xuất khẩu.