面向对象和序列化 [英] Object orientation and serialization

查看:97
本文介绍了面向对象和序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑类似的界面

IMyInterface = interface
  procedure DoSomethingRelevant;
  procedure Load (Stream : TStream);
  procedure Save (Stream : TStream);
end;

和一些实现该接口的类:

and several classes that implement the interface:

TImplementingClass1 = class (TInterfacedObject, IMyInterface)
  ...
end;
TImplementingClass2 = class (TInterfacedObject, IMyInterface)
  ...
end;
...

我有一个包含IMyInterface实现者列表的类:

I have a class that has a list of IMyInterface implementors:

TMainClass = class
strict private
  FItems : TList <IMyInterface>;
public
  procedure LoadFromFile (const FileName : String);
  procedure SaveToFile (const FileName : String);
end;

现在的问题是:如何以面向对象的方式加载主类,尤其是项目列表?在我可以为项目调用虚拟Load方法之前,我必须创建它们并因此必须知道它们的类型.在我当前的实现中,我存储了项目数,然后存储了每个项目

Now to the question: how can I load the main class and especially the item list in an object-oriented manner? Before I can call the virtual Load method for the items, I have to create them and thus have to know their type. In my current implementation I store the number of items and then for each item

  • 类型标识符(IMyInterface获得附加的GetID函数)
  • 调用该项的Save方法

但这意味着在加载过程中,我必须做类似的事情

But that means that during loading I have to do something like

ID := Reader.ReadInteger;
case ID of
  itClass1 : Item := TImplementingClass1.Create;
  itClass2 : Item := TImplementingClass2.Create;
  ...
end;
Item.Load (Stream);

但是,这似乎不是非常面向对象的,因为每次添加新的实现程序时,我都不得不摆弄现有的代码.有没有更好的方法来处理这种情况?

But that doesn't seem to be very object-oriented since I have to fiddle with existing code every time I add a new implementor. Is there a better way to handle this situation?

推荐答案

一种解决方案是实现一个工厂,所有类都使用唯一的ID自行注册.

One solution would be to implement a factory where all classes register themselve with a unique ID.

TCustomClassFactory = class(TObject)
public      
  procedure Register(AClass: TClass; ID: Integer);
  function Create(const ID: Integer): IMyInterface;
end;

TProductionClassFactory = class(TCustomClassFactory)
public
  constructor Create; override;
end;

TTestcase1ClassFactory = class(TCustomClassFactory);
public
  constructor Create; override;
end;

var
  //***** Set to TProductionClassFactory for you production code,
  //      TTestcaseXFactory for testcases or pass a factory to your loader object.
  GlobalClassFactory: TCustomClassFactory;

implementation

constructor TProductionClassFactory.Create;
begin
  inherited Create;
  Register(TMyImplementingClass1, 1);
  Register(TMyImplementingClass2, 2);
end;

constructor TTestcase1ClassFactory.Create;
begin
  inherited Create;
  Register(TMyImplementingClass1, 1);
  Register(TDoesNotImplementIMyInterface, 2);
  Register(TDuplicateID, 1);
  Register(TGap, 4);
  ...
end;

优势

  • 您可以从当前的加载方法中删除条件逻辑.
  • 一个可以检查ID重复或缺失的地方.

这篇关于面向对象和序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆