C ++中的设计模式

2020-12-19 01:56:59

我知道的对“设计模式”的第一个参考是著名的GoF书:

这本书是编程的经典著作,它位于世界各地许多程序员的桌上。

本书描述的设计模式是多种结构化代码以解决特定问题的方法。这些模式已标记有“策略”,“访问者”,“适配器”,“命令链”等名称。

设计模式不是特定于语言的:它们可以以C ++,Java,C#和许多其他语言应用。但是GoF书中的代码示例是C ++和Smalltalk。

有关这些设计模式的详细分析,请参阅我的系列文章“设计模式与设计原则”。在这篇文章中,我想深入了解C ++中设计模式的一般方面,而我在GoF书中并不容易理解。

关于设计模式的开创性书籍有C ++示例!幸运的我们!要了解如何在C ++中应用设计模式,我们可以看看GoF书中的代码片段,对吧?

GoF书中使用的C ++功能没有利用C ++提供的所有编程范例。

主要原因是设计模式严重依赖于多态性,而本书在其示例中专门使用了运行时多态性,即继承和虚拟方法。

class EquipmentVisitor { 上市: 虚拟〜EquipmentVisitor(); 虚拟void VisitFloppyDisk(FloppyDisk *); 虚拟无效VisitCard(Card *); 虚拟void VisitChassis(Chassis *); 虚拟void VisitBus(Bus *); //等等,以此类推。 受保护的: EquipmentVisitor(); }; PricingVisitor类:公共EquipmentVisitor { 上市: PricingVisitor(); 货币和GetTotalPrice(); 虚拟void VisitFloppyDisk(FloppyDisk *); 虚拟无效VisitCard(Card *); 虚拟void VisitChassis(Chassis *); 虚拟void VisitBus(Bus *); // ... 私人的: 货币_总计; };

这是用C ++实现Visitor的一种可能方式,并且没有使用该语言的特殊性。我们将在下面看到另一个。在上面的代码中,我们只需重新排列关键字的位置,然后将此代码转换为Java。

明确地说,我的目标不是选择GoF书。这是一本很棒的书,读起来很有趣,而且尽管它是25年前写的,但今天仍然有意义。设计目录和本书的第一部分(在目录之前)都包含有价值的设计课程。

但是在阅读GoF书之后,您可能会觉得这是在C ++中实现设计模式的唯一方法。这是不正确的。

GoF书之后出版的另一本关于设计模式的书是Andrei Alexandrescu的Modern C ++ Design:

本书的标题不是很具体,但请查看副标题:“应用的通用编程和设计模式”。通用编程是指模板。本书是关于使用模板实现设计模式的。

实际上,这本书的内容还不止这些。它显示了高级模板和设计技术。它使用这些技术以非常特定于C ++的方式来实现设计模式。

这是我一直以来最喜欢的C ++书,我建议您看看。模板自2001年发布以来,已经有些陈旧了,早于可变参数模板进入标准之前,但是它模仿了带有类型列表的可变参数模板。

拥有具有C ++ 20功能的本书修订版真是太棒了。如今,本书的内容仍然很有趣,而且令人印象深刻!

我们将不在这里介绍先进的技术现代C ++设计。相反,我们将在C ++标准库中看到两个简单的示例,这些示例将设计模式与继承和虚拟方法以外的其他工具一起使用。

自动数字= std :: vector< {0,1,2,3,4,4,5,6,7,8,9}; std :: for_each(begin(numbers),end(numbers),[](int& i){i * = 10;}); //数字现在包含{0,10,20,30,40,50,60,70,80,90}

std :: for_each实现设计模式策略。实际上,它采用了一个多态参数,并在其代码中使用了它。我们可以将任何函数传递给for_each,只要它接受迭代器表示的范围内的参数类型即可。

与继承和虚拟方法相反,这不是运行时多态。这是基于模板的编译时多态,在编译时已解决。

公平地说,尽管GoF书中没有提到std :: for_each,但其中提到的一种实现方式是C ++允许使用模板参数来实现Strategy。

让我们再以访客设计模式为例。本质上,Visitor是指您具有要应用于多态对象的多态函数。

GoF书通过两个类的层次结构对此进行了说明,并展示了它们如何相互调用虚拟方法来依次解析两个多态实例。

再次与一本优秀的GoF书籍相提并论,它提到这是一种补偿C ++没有实现的双重调度技术的方法(它提到了CLOS语言实现了它),这表明类的双重层次结构是不是实现模式的唯一方法。

C ++ 17的std :: visit提供了另一个实现Visitor设计模式的示例。 std :: visit是一种在std :: variant上应用函数的方法。但是根据定义,由于std :: variant可以容纳不同类型的值,因此我们可能需要各种函数对其进行操作。

考虑以下示例。这是创建可在C ++中对各种类型进行操作的函数对象的多种技术之一:

结构访客 { std :: string运算符()(std :: string const& s){return s; } template< typename T> std :: string运算符()(T const& value){返回std :: to_string(value);} };

现在假设我们有一个允许获取变体对象的函数: 在这里,被访问对象(变体)使用运行时多态(即使没有继承和虚拟方法),而访问者对象(Visitor)则使用基于重载解析的编译时多态。 即使GoF书籍暗示存在其他可能的实现,其代码示例也大量使用了继承和虚拟方法。 这是一种实现多态性的方法,它有其优点和缺点。 但是请记住,C ++是一种丰富的语言,可以提供各种类型的多态性,包括提供不同折衷方案的编译时多态性。 请注意您可以使用的许多工具,以便能够在遇到的情况下使用最适合的工具。 成为赞助人! 分享这个帖子! &nbspDon不想错过吗? 跟随: