【问题标题】:How to make an Abstract class into a Singleton Object?如何将抽象类变成单例对象?
【发布时间】:2014-10-06 16:28:34
【问题描述】:

案件内容: 问题是这样的——为了让我的程序跨平台,我为操作系统执行的操作做了一个抽象层。有一个抽象基类,名为SystemComponent,看起来像这样:

class SystemComponent{
public:
    //some functions related to operations for OS
    virtual WindowHandle CreateNewWindow(/*...*/) = 0;
    virtual void Show_Message(/*...*/)            = 0;
    //...
}

这会被另一个操作系统特定的类继承,比如 Windows 的WindowsSystemComponent

#ifdef _WIN23

class WindowsSystemComponent   :   SystemComponent{
public:
    virtual WindowHandle CreateNewWindow(/*...*/);
    virtual void Show_Message(/*...*/);
    //...
protected:
    //Windows specific things...
}

#endif

这个WindowsSystemComponent 然后隐含了操作系统特定的功能。

要在 Windows 中创建系统组件,我这样做:

WindowsSytemComponent* pWSystemComp = new WindowSystemComponent();
//...
//And the pass a pointer to this to the crossplatform code like this
pFrameWork->SetSystem((SystemComponent*)pWSystemComp);

框架调用SystemComponent 中指定的操作系统函数,并将指针传递给任何需要它的子类。

需要什么: 我想删除指针的传递,并使 SystemComponent 类和操作系统特定的函数实现对每个想要使用它们的对象都可访问。最好的方法是让它成为一个单例,但是当我尝试做类似的事情时

virtual static SystemComponent* Instance() { /*...*/ };

在抽象的SystemComponent 类中,我得到一个编译器错误,说这样的事情是不允许的。

那我应该怎么做呢?

【问题讨论】:

标签: c++ inheritance singleton


【解决方案1】:

你不能有一个虚拟的静态方法,但 Instance 方法不需要是虚拟的——它只需要为你运行的平​​台创建正确类型的 SystemComponent。您只需要使用您现在使用的代码为平台创建 SystemComponent 实例并将其放入 Instance 方法中。

【讨论】:

  • 但是如果WindowsSystemComponent 的存在对于SystemComponent 类不知道呢?
  • @TheLightSpark -- 头文件不需要知道特定于平台的组件,只需要知道实现。您可以在特定于平台的源文件中有不同的实现(这是我想象您现在创建实例时正在做的事情,除非您有特定于平台的框架初始化代码)
【解决方案2】:

解决这个问题的另一种方法是模拟单例的概念,但让派生类设置要使用的单例。

class SystemComponent
{
  public:
    static SystemComponent* instance()
    {
       return theInstance_;
    }

    //some functions related to operations for OS
    virtual WindowHandle CreateNewWindow(/*...*/) = 0;
    virtual void Show_Message(/*...*/)            = 0;
    //...

  protected:

    static setInstance(SystemComponent* in)
    {
      theInstance = in;
    }
}

// Define the static member.
SystemComponent* SystemComponent::theInstance = nullptr;

使用WIN32时,确保WindowsSytemComponent为单例,并在初始化时在基类中设置实例。

SystemComponent::setInstance(WindowsSytemComponent::instance());

当使用另一个平台时,做类似的事情。

SystemComponent::setInstance(AnotherPlatformSytemComponent::instance());

【讨论】:

    【解决方案3】:

    这不能按照您提议的方式完成。但我认为可以解决您的问题的是使用工厂模式。 Wikipedia

    你可以这样做:

    class SystemComponentFactory
    {
       static SystemComponent* ptr = 0;
    
       static SystemComponent getSystemComponent()
       {
         if ( ptr == 0 )
         {
           if ( isWindows() )
              ptr = new WindowsSytemComponent();
           else if ( isLinux() )
              ptr = new XwindowsSystemComponent();
           ...
         }
         return ptr;
       }
    };
    

    【讨论】:

      【解决方案4】:

      您将无法实例化抽象类。 单例模式将类的实例化限制为一个对象。这与之前的约束相冲突。你最好考虑使用abstract factory pattern

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-06
        • 1970-01-01
        • 2022-12-17
        • 1970-01-01
        • 2021-08-30
        相关资源
        最近更新 更多