C++:类功能子集的推荐设计模式

C++: recommended design pattern for subsets of class functionality?

本文关键字:设计模式 子集 功能 C++      更新时间:2023-10-16

我正在寻求一种非常适合我需求的设计模式的建议:

在我的C++项目中,一个特定的纯虚拟类将代表某个概念的所有相关功能的超集,而从该纯虚拟类派生的具体类将分别是该超集的一些不同的有限子集。在运行时,这些具体类中只有一个实例存在。

如果我用C语言编程,我可能会选择将其实现为函数指针的结构,并为任何缺失的功能使用NULL。但这对C++来说并不是很令人满意。

我能想到的唯一想法是一个将每个成员函数都作为"protected"的类,以及一组匹配的"public"成员函数指针。构造函数将负责将MFP初始化为NULL或相应成员函数的地址,具体取决于该类提供的功能。

但这实际上只比我上面第一次提到的函数的C结构多了一点C++。而且,也许这已经足够好了。但我想知道是否有人能为这个场景提出一个更令人满意、更有洞察力的设计模式。

我对任何公认的做法都持开放态度。STL很好。

UPDATE:MFP方法不太令人满意的原因是,由于纯虚拟基类的原因,我将不得不为那些不应用的方法实现无所事事的存根,即使我将它们各自的MFP设置为NULL 经过进一步思考,这次更新完全是伪造的。(它们不会是无所事事的存根,它们将是有用的功能,在MFP不使用NULL的情况下。我想我已经累了。)

UPDATE 2:一个类比:我的项目支持可以交换的硬件模块。它们基本上都是同一类功能,但在特性和功能上有所不同。在启动时,我必须检测实际连接的硬件模块,并实例化适当的类。但我不希望使用该类的代码对每个类都有专门的知识;我希望该类公布它提供的功能。(有时,两个硬件模块会识别为相同的类型ID,但在功能探测时,其中一个会指示另一个没有的功能。)

您的设计需求违反了一个非常重要的OOP原则。如果一个类或函数依赖于该"超集"接口,那么编译器将永远无法强制执行类型安全性——你本质上是在与它作斗争,为了什么?

我建议您隔离接口,并创建一个具体的(可能是纯虚拟的)类来实现所有接口。这种设计模式有一个名字,叫做facade。

更新我现在阅读了您的更新,我认为您需要一个提升对象的工具。有两种促销:

  • 实施促销:
    这是基本上替换对象实现的地方。这可以通过状态模式来完成,也可以通过将对象放置为具有不同VTABLE的对象来完成
  • 功能性促销:
    这就是添加功能的地方,就像在更多功能中一样。您可以通过从硬件模块的名称到其变体指针的映射来实现这一点。当您将对象提升到不同的类时,只需替换指针变体。例如,如果您的第一个映射来自"COM1"->GenericSerial*,那么您现在设置"COM1"->SpecializedSerial*。您可以使用诸如boost之类的变体库

为什么不这样做:

interface All {
    void f1();
    void f2();
    void f3();
}
abstract class AllABC implements All {
    public void f1() {
        throw new RuntimeException("not implemented");
    }
    public void f2() {
        throw new RuntimeException("not implemented");
    }
    public void f3() {
        throw new RuntimeException("not implemented");
    }
}
class F12 extends AllABC {
    public void f1() {
        System.out.println("f1");
    }
    public void f2() {
        System.out.println("f2");
    }
}
class F13 extends AllABC {
    public void f1() {
        System.out.println("f1");
    }
    public void f3() {
        System.out.println("f3");
    }
}
public class So20511733 {
    public static void main(String[] arguments) {
        All f12=new F12();
        f12.f1();
        f12.f2();
        All f13=new F13();
        f13.f1();
        f13.f3();
    }
}