如何在 Delphi 中拥有一个在运行时和设计时工作的单例

Posted

技术标签:

【中文标题】如何在 Delphi 中拥有一个在运行时和设计时工作的单例【英文标题】:How to have a Singleton that works at runtime and design time in Delphi 【发布时间】:2014-01-04 05:55:38 【问题描述】:

德尔福 XE2

我是组件开发的新手。

我有一个单例类“TThemeManager”,其中包含我在应用程序中使用的调色板颜色集合。整个应用程序只需要一个 ThemeManager 并且只使用一个主题,有一种方法可以定义哪个。

这个类是在单元的初始化部分创建的,它在一个全局变量上声明它:

var
  NaharThemeManager: TNaharThemeManager;

implementation

...

initialization  
  if Not Assigned(NaharThemeManager) then
    NaharThemeManager := TNaharThemeManager.Create;

这在应用程序上运行良好,它始终可用。

然后我创建了一些组件,为此使用 Delphi 向导,没什么特别的,我只添加了一个属性,我可以从当前主题中选择我想要该组件的颜色。

  TNaharWEBPanel = class(TPanel)
  private
  private
    FThemeColor : TNaharPalleteColor;
    procedure   OnObserver(Sender: TObject; AParam, AValue: Variant);
    procedure   UpdateColor;
    procedure   SetColor(const Value: TNaharPalleteColor);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
  published
    property    ThemeColor: TNaharPalleteColor read FThemeColor write SetColor default npcMainColor;
  end;

设置主题颜色时:

procedure TNaharWEBPanel.SetColor(const Value: TNaharPalleteColor);
begin
  FThemeColor := Value;

  UpdateColor;
end;

procedure TNaharWEBPanel.UpdateColor;
begin
  if FThemeColor <> npcNone then
  begin
    Color := NaharThemeManager.CurrentPallete.Color[FThemeColor];

    Font.Color := NaharThemeManager.CurrentPallete.HighContrast(FThemeColor);
  end;
end;

NaharThemeManager 是单例类。或者应该是。但是,如果我像这样放置几个面板,它们不会使用相同的单例。它似乎每个组件都有一个。我不知道如何调试这个,所以我只能看到问题的证据

当我让应用程序运行时,我的组件和应用程序之间的单例并不相同。

我必须做些什么才能真正拥有这个对象的一个​​单例?

【问题讨论】:

正在创建和使用单例,那么为什么您认为每个面板都使用不同的管理器实例?你是怎么检查的?您所描述的内容只有在您的项目在内存中有多个经理单元实例时才有可能,并且在正常情况下这不应该是可能的,否则您将收到“重复单元”异常。 我的单例中有一个 AddObserver,我的每个可视组件都调用 ThemeManager.AddObserver(self)。因此,例如,如果主题发生更改,单例将通知所有组件。我创建了一个非可视组件,仅显示有关此单例的信息,并且我放置了一个已发布的属性来显示添加到单例中的观察者数量,它只显示 1。如果我更改主题(通过这个非可视组件)只有一个面板收到通知并更改其颜色。我在同一个 TFrame 上有很多面板,都应该得到通知。 由于您没有显示任何代码,我只能假设您的观察者逻辑可能存在错误,例如,如果它只保留一个注册观察者并丢弃其他观察者。如果您需要帮助,请提供SCCCE 显示您正在做的所有事情。 @RemyLebeau 没错,我重新检查了我的观察者逻辑,它只注册了第一个组件,之后忽略了所有内容。这就是为什么只通知一个。我解决了这个问题,现在一切正常。 Singletong 确实在设计模式下跨单元工作。谢谢。 我发布了我的 cmets 作为答案,以便您接受。 【参考方案1】:

您正在创建和使用单例,因此每个面板都应该使用相同的管理器实例。您所描述的内容只有在您的项目在内存中有多个经理单元实例时才有可能,而这在正常情况下是不可能的,否则您将收到“重复单元”异常。

更有可能的罪魁祸首是您的观察者逻辑中存在错误,例如它只保留一个已注册的观察者并丢弃其他观察者。

【讨论】:

以上是关于如何在 Delphi 中拥有一个在运行时和设计时工作的单例的主要内容,如果未能解决你的问题,请参考以下文章

Azure 流分析:如何在运行时和以编程方式更新查询?

delphi7中如何引入外部的dll文件

malloc如何在编译时和运行时处理? [关闭]

是否在编译时和运行时都调用了ld?

Delphi XE6 Firemonkey Mobile - 如何禁用虚拟键盘?

JavaScript是如何工作的01:引擎,运行时和调用堆栈的概述!