如何在Delphi中创建在运行时和设计时工作的单例

如何在Delphi中创建在运行时和设计时工作的单例,delphi,singleton,components,delphi-xe2,Delphi,Singleton,Components,Delphi Xe2,德尔福XE2 我是组件开发的新手 我有一个单例类“TThemeManager”,它包含我在应用程序中使用的托盘颜色集合。整个应用程序只需要一个主题管理器,并且只使用一个主题,有一种方法可以定义哪个主题 此类是在单元的初始化部分创建的,该单元在全局变量上声明此类: var NaharThemeManager: TNaharThemeManager; implementation 这在应用程序上运行良好,它始终可用 然后我使用Delphi向导创建了一些组件,没有什么特别的,我只添加了一个属

德尔福XE2

我是组件开发的新手

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

此类是在单元的初始化部分创建的,该单元在全局变量上声明此类:

var
  NaharThemeManager: TNaharThemeManager;

implementation

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

然后我使用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;
procedure TNaharWEBPanel.SetColor(常量值:TNaharPalleteColor);
开始
FThemeColor:=值;
更新颜色;
结束;
程序TNaharWEBPanel.UpdateColor;
开始
如果FThemeColor npcNone,则
开始
颜色:=nahartememanager.CurrentPallete.Color[FThemeColor];
Font.Color:=nahartememanager.CurrentPallete.HighContrast(FThemeColor);
结束;
结束;
那个经理是单身族。或者应该是。但是,如果我放置几个这样的面板,它们不会使用相同的单体。似乎每个组件都有一个。我不知道如何调试这个,所以我只能看到问题的证据

当我让应用程序运行时,我的组件和应用程序中的单例就不一样了


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

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


更可能的罪魁祸首是您的观察者逻辑中有一个bug,如果它只保留一个已注册的观察者而丢弃其他观察者,那么就是这样。

您正在创建和使用一个单例,那么为什么您认为每个面板都使用不同的管理器实例?你怎么查到的?您所描述的内容只有在您的项目内存中有多个manager单元实例时才可能实现,而在正常情况下这不可能实现,否则您将引发“重复单元”异常。我的singleton上有一个AddObserver,其中我的每个可视组件都调用manager.AddObserver(self)。因此,例如,如果主题发生更改,singleton将通知所有组件。我创建了一个非可视组件,仅用于显示有关此单例的信息,并放置了一个已发布的属性以显示添加到该单例的观察者的数量,它仅显示1。如果我更改了主题(通过这个非视觉组件),只有一个面板会收到通知并更改其颜色。我在同一个TFrame上有许多面板,所有面板都应该得到通知。由于您没有显示任何代码,我只能假设您的观察者逻辑中可能存在错误,例如,如果它只保留一个已注册的观察者,而丢弃其他观察者。如果您需要帮助,请提供一个显示您所做的一切的列表。@RemyLebeau如果您说得对,我重新检查了我的观察者逻辑,它只注册第一个组件,然后忽略所有内容。这就是为什么只通知一个。我已经修好了,现在一切都正常了。Singletong在设计模式下跨单元工作。谢谢。我把我的评论贴出来作为回答,这样你就可以接受了。
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;