Context
我尝试在 Delphi 中创建一个通用的“Observer”模式,我成功地实现了一些功能:
TObserver = class
protected
FSubject: TSubject;
public
constructor Create(); virtual; overload;
constructor Create( constref subject: TSubject ); virtual; overload;
destructor Destroy(); virtual;
procedure ReAttach( constref newSubject: TSubject ); virtual;
procedure Update(constref subject: TSubject); virtual;
end;
TSubject = class
protected
FObservers: TList<TObserver>;
public
constructor Create; overload;
destructor Destroy; override;
procedure Notify(); virtual;
procedure Attach(constref AObserver: TObserver); virtual;
procedure Detach(constref AObserver: TObserver); virtual;
end;
每个新的回调签名都需要扩展TSubject和TObserver。这很快就变得乏味。
TMyObserver = class( TObserver )
public
type TCallback = procedure (...) of object;
private
FCallback: TCallback;
public
property Callback: TCallback read FCallback write FCallback;
procedure Update(constref subject: TSubject, ...); overload;
end;
TMySubject = class( TSubject )
...
这是不切实际的,所以我想知道是否有更好的方法。
例如,在C++中,有一个叫做Variadic Templates
的东西,在 Delphi 中可能会被称为Variadic Generics
。
#include <iostream>
#include <functional>
template <typename ...UpdateArgs>
class Observer
{
public:
using CallbackType = std::function<void(UpdateArgs...)>;
CallbackType callback;
void Update(UpdateArgs... args)
{
if (callback) callback(args...);
}
};
int main()
{
Observer<int, const std::string&> obs1;
obs1.callback = [](int vInt, const std::string& vStr)
{
std::cout << "Int is: " << vInt << " and String is: '" << vStr << "'" << std::endl;
};
obs1.Update(42, "Hi you");
// OR
Observer<float> obs2;
obs2.callback = [](float f)
{
std::cout << "Float is: " << f << std::endl;
};
obs2.Update(3.1415926);
return 0;
}
Test it live here
对于那些不太熟悉C++的人来说,这基本上是一个带有可变数量参数的泛型Observer
。使回调可用于所需参数的确切类型和数量。
提问
Delphi 有Variadic泛型吗?也就是说,一种指定可变参数集的方法,允许为每个所需的通知签名专门指定TObserver
和TSubject
。
我希望解决方案是类型安全的。
否则,还有什么选择?
1条答案
按热度按时间w8rqjzmb1#
Delphi 有Variadic泛型吗?
不,不是的。泛型所能做的一切都在Embarcadero的DocWiki中得到了完整的记录:
https://docwiki.embarcadero.com/RADStudio/en/Generics_Index