问题标签 [policy-based-design]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 理解 Alexandrescu 关于多重继承弱点的阐述
更新:我在这里问了一个更狭窄的问题。
在Modern C++ DesignC++
的第 6-7 页上,Andrei Alexandrescu 对两种语言特性(多重继承和模板)在构建灵活设计方面的优缺点进行了非常基本的讨论。他总结道:
现在将多重继承的缺点列表与模板的缺点列表进行比较。有趣的是,多重继承和模板促进了互补的权衡。多重继承机制稀缺;模板具有丰富的机制。多重继承会丢失模板中丰富的类型信息。模板的专门化无法扩展,但多重继承可以很好地扩展。您只能为模板成员函数提供一个默认值,但您可以编写无限数量的基类。
我能感觉到安德烈在这里所说的非常重要,但如果没有任何例子来说明要点,我无法真正理解所说的内容。这个问题要求提供简单的例子来说明这些观点(请继续阅读)。
为了使问题更具体,我想请您关注多重继承的弱点。这就是安德烈对他们的评价(方括号中的文字是我对上下文的理解):
在这样的设置中[即多重继承],[构建一个灵活的,]用户将通过继承一些类和两个类
SmartPtr
来构建一个多线程、引用计数的智能指针类:和。任何有经验的类设计师都知道,这种幼稚的设计是行不通的。BaseSmartPtr
MultiThreaded
RefCounted
分析多重继承无法创建灵活设计的原因为达成合理的解决方案提供了有趣的想法。使用多重继承组装单独的特征的问题如下:
- 力学。没有样板代码可以以受控方式组装继承的组件。唯一结合 BaseSmartPtr、MultiThreaded 和 RefCounted 的工具是一种称为多重继承的语言机制。该语言在组合基类时应用了简单的叠加,并建立了一组访问其成员的简单规则。除了最简单的情况外,这是不可接受的。大多数时候,您需要仔细协调继承类的工作以获得所需的行为。
- 类型信息。基类没有足够的类型信息来执行它们的任务。例如,假设您尝试通过从 DeepCopy 基类派生来为您的智能指针类实现深度复制。但是 DeepCopy 会有什么接口呢?它必须创建它还不知道的类型的对象。
- 状态操纵。使用基类实现的各种行为方面必须操纵相同的状态。这意味着他们必须使用虚拟继承来继承持有状态的基类。这使设计复杂化并使其更加僵化,因为前提是用户类继承库类,反之亦然。
对于上述三个项目中的每一个,我都非常感谢一个简单的例子。每个示例都将显示多重继承的一个限制(例如,糟糕的机制)以及模板如何不具备这种限制(Andrei 写道“多重继承和模板促进互补权衡”)。
c++ - 多重继承机制与构建灵活设计的模板相比
这是由于过于宽泛而搁置的问题的较窄版本。
在Modern C++ Design的第 6-7 页上,Andrei Alexandrescu 列出了在构建灵活设计方面多重继承弱于模板的三种方式。特别是,他指出多重继承提供的机制很差(根据我对上下文的理解,方括号中的文本和格式是我的):
在这样的设置中[即多重继承],[构建一个灵活的,]用户将通过继承一些类和两个类
SmartPtr
来构建一个多线程、引用计数的智能指针类:和。任何有经验的类设计师都知道,这种幼稚的设计是行不通的。BaseSmartPtr
MultiThreaded
RefCounted
...
- 力学。没有样板代码可以以受控方式组装继承的组件。唯一结合 BaseSmartPtr、MultiThreaded 和 RefCounted 的工具是一种称为多重继承的语言机制。该语言在组合基类时应用了简单的叠加,并建立了一组访问其成员的简单规则。除了最简单的情况外,这是不可接受的。大多数时候,您需要仔细协调继承类的工作以获得所需的行为。
使用多重继承时,可以通过编写调用多个基类的成员函数的成员函数来实现一些非常灵活的编排。那么,多重继承中缺少并存在于模板中的编排是什么?
请注意,与模板相比,并不是多重继承的所有缺点都可以作为答案,而只是上面引用中 Andei 所谓的机制的缺点。特别是,请确保您不是在谈论Andrei 列出的其他两个多重继承弱点之一:
类型信息。基类没有足够的类型信息来执行它们的任务。例如,假设您尝试通过从 DeepCopy 基类派生来为您的智能指针类实现深度复制。但是 DeepCopy 会有什么接口呢?它必须创建它还不知道的类型的对象。
状态操纵。使用基类实现的各种行为方面必须操纵相同的状态。这意味着他们必须使用虚拟继承来继承持有状态的基类。这使设计复杂化并使其更加僵化,因为前提是用户类继承库类,反之亦然。
c++ - 具有不同接口的策略类
假设一个算法有一个策略FooPolicy
。实现此策略的策略类具有静态成员函数foo
,但对于其中一些,它foo
接受一个int
参数,而对于其他一些则没有。我正在尝试通过constexpr
静态数据成员启用这些具有不同接口的策略类:
此代码无法编译。gcc 4.8.2
给出错误:
调用 'ParamFoo::foo()' 没有匹配的函数</p>
否则 FooPolicy::foo();
尽管该else
子句在编译时是已知的,但仍会编译FooPolicy::paramFlag
该子句true
。有没有办法让它工作?
c++ - Decoupling host and policy classes at the cost of stateful policy classes and not following Item 26 of Effective C++
This post consists of describing a problem with the straightforward implementation of the policy-based design, proposing an alternative implementation, analyzing the proposed implementation and asking help in giving correct weight to the different factors in the analysis. I apologize for the length of the post and hope that you will stick with me.
PROBLEM DESCRIPTION
Suppose that we use policy-based design as follows:
There is a degree of coupling between the above host class and the policy: if the signature of FooPolicy::foo
changes, then the code in Alg::operator()
has to change accordingly.
The coupling becomes much tighter if policy classes are given a degree of freedom for choosing an interface. For example, suppose that FooPolicy
may implement either foo
without parameters or foo
with one integer parameter (the implementation for this case was suggested here):
Obviously, whenever one adds a policy class with a different interface, he will have to update the dispatching mechanism, which can become complicated.
PROPOSED DESIGN
I am considering a design, whereby the algorithm would provide an interface that function members of the policy class can use to get data instead of accepting arguments. For the above example, it might look as follows:
ANALYSIS
With this design, a policy is free to use any data obtainable by using the public interface of the corresponding Services
class. In our example, ParamFoo::foo
got the algorithm's arg
by using FooPolicyServices::getArg
. The host class simply calls FooPolicy::foo
without arguments and this will not have to change even if FooPolicy::foo
changes, which is the decoupling we wanted.
I see two disadvantages to this design:
arg
has become part of the state ofAlg
instead of being a local variable inAlg::operator()
, which goes against Item 26 of Effective C++ saying that variables should be defined as late as possible. However, the reasoning of that item does not apply if the cost of the extra initialization ofarg
is negligible compared to the cost of running the algorithm.Policy classes have gotten a state. So, we cannot use policies by simply calling their static member functions.
QUESTIONS
Three questions:
Is the decoupling achieved by the proposed design worth the two disadvantages listed above?
Are there disadvantages that I overlooked?
Does the proposed design have a name?
Based on the reply by @Useless, here is an updated implementation. This implementation makes it possible to have stateless policy classes, but has an overhead of passing the same reference to a Services
object each time a policy is used.
c++ - 基于 C++ 策略的设计
在基于 Alexandrescu策略的设计中,我不理解的是创建没有任何共同点的新类型,在我看来,仍然有很多共同点应该以某种方式表示。
例如,std::string
and std::basic_string<>
: 分配器是非常内部的东西,在我看来,使用该类的代码不应知道该类正在使用哪个分配器。
但是由于已经创建了一个新类型,比如说std::basic_string_1
,所有那些在 an 周围传递的方法std::string&
基本上都被破坏了,而且我看不出一个正当的理由,为什么带有不同分配器的 an 应该被认为与带有另一个分配器std::basic_string<>
的完全不同。std::basic_string<>
我的问题是:为什么每个人都没有共同的父母std::basic_string<>
,这样就可以避免这个问题?通常在我的代码中,当我有 a 时Whatever<T>
,我让它继承自WhateverBase
某种 a ,并且当T
没有显示在该类的公共接口上时,它可以很好地工作......
c++ - 策略类的配置
我想知道在基于策略的设计中配置策略的最佳实践是什么。策略的接口由其宿主类定义。然而,没有定义如何实现这个接口。因此,策略可能需要不同的配置参数。但我只想将一个配置(对象)提供给宿主类。以下代码是我目前所做的一个草稿,但我对它不太满意,因为它不保证不存在命名冲突,也不封装不同策略的配置成员。
如何防止配置对象中的名称冲突?是否有一些类似于命名空间的机制?或者是否有更好的想法来配置我的策略?
c++ - C++ 策略对象和构建器模式
我有一些Builder
构建Object
. 我计划Object
用策略对象替换一些 的胆量,例如能够设置一些容器类型Storage
。具体来说,我想使用Builder
来设置 的策略对象,Object
如果没有指定则回退到某个默认值;在我的头顶上,像这样:
问题的症结在于:我可以使用 typedef 作为一种“模板变量”,以便存储用户定义的模板变量吗?
为了提供更多上下文,Builder
必须支持从 json 配置文件创建相当复杂Object
的文件,将每个键及其验证委托给单个方法。我有一个静态命名构造函数Builder::from_config(...)
和一个Builder::load_config(...)
为我做这件事的方法,但我想支持从配置文件中选择策略对象。否则,我只需将模板添加到Builder::init()
方法中就可以了,这样我就可以将我的策略对象传递给Object
.
c++ - 基于策略的设计中的 C++ 复制/移动构造函数
在探索 C++ 中基于策略的设计模式时,我偶然发现了一个我找不到解决方案的问题:如何在不引用策略类中的成员变量的情况下以通用方式为基于策略的类编写复制和移动构造函数?
这是一个例子:
在上面的代码中,复制构造函数class Foo
使用受保护的成员变量来初始化Base
类。Base
除了上述之外,还有其他方法可以初始化吗?在这种情况下,最佳做法是什么?
更新的问题:
@LogicStuff 的回答澄清了问题的复制构造函数部分,但没有回答移动构造函数问题。请参阅更新的示例代码,其中class Foo
也可以包含成员变量。
c++ - 创建一个类模板,该类模板可以将由自身创建的类作为参数
有没有办法创建一个可以将自身实例化作为模板参数的类模板?
我希望能够在我的代码中这样说:
我尝试使用可变参数模板参数定义这样的类模板,以避免陷入无限循环(模板必须定义一个模板模板参数,该参数本身接受一个模板参数,该模板参数本身也必须接受一个模板参数等等。 .)。
typename... OP
应该能够采取一个Operation<T>
甚至一个Operation<T, Operation<T>>
这可能吗?
背景:我正在尝试构建基于策略的函子,这些函子可以组合起来形成算术“连锁反应”。一个操作使用一个Function
策略类来确定它应该做什么,它还将使用两个 Source 对象作为参数。源对象可能是Function
策略或其他对象Operation
,因为这两者都定义了函数T execute()
。最终目标是通过调用这些函子在运行时根据命令执行这些算术运算。