政策是一种聪明的开关机制。它们用于以下任何一种情况:
- 带有一个模板工厂的工厂模式,该模板工厂在产品之间切换。
- 带有一个模板类的策略模式,该模板类在行为之间切换。
- 具有不同类型属性包的类。例如,您拥有一辆车,在策略中,您可以具有行为。
引用:
“这个想法是继承文件并创建不同的模板,以后需要时可以生成。这对政策来说是否合适,或者我应该将文件句柄传递给全局静态函数,或者我应该为每种类型的文件创建一个类?我想确保用户错误很低:),而政策似乎不容易出错。”
你可以按你说的方式走,下面是每个方法的优缺点:
- 全局静态函数
优点:
- 如果你计划进行小程序那还有什么好担心的?使用它们然后释放并停止开发
缺点:
- 您的实现可能需要其他地方的额外数据,这意味着事物可能会变得不成比例。
- 随着程序的增长,您可能希望在全局静态函数之间共享内容,因此您删除静态内容,然后开始使用全局变量,然后是混乱,这需要大约3年的时间。如果适用于您的情况,请注意。
- 你想在一个线程中运行一组函数,在另一个线程中运行另一个函数,因此你创建一个函数管理器类,使用全局静态函数需要进行繁琐的重构。
- 每种文件类型的类
优点:
- 有很多关于如何做到这一点的教程
缺点:
- 随着程序的增长,要跟踪的类会越来越多。
- 大量的…………模版代码需要重写
- 它基本上与使用模板相同,如果您可以想出一个模板主类,那么某些执行问题就限制在其中,而不是扩散到其余文件中。
- 政策(免责声明:我喜欢政策)
优点:
- 统治所有的一个主人接口
- 在编译时创建代码,因此每个使用的代码都为一个类。
- 与许多锅炉板-y类相比,易于维护。
缺点:
- 如Alexandrescu所述,一些模板编码可能使编译优化无效。
- 设计更难,理解更难,实现更难。
- 更容易的路径可能会吸引您,您可能会退出实现并像小女孩一样哭着回到全局静态函数。
一个运行方法根据您的算法可以延伸到数千行代码。
大多数示例展示了构造、析构、线程安全等部分。简单来说,这是因为它们只是小的示例,策略只能扩展到你的想象力。请记住,你是程序员,你可以把代码推向前所未有的高度。如果你不这样做,没有人会。
还记得弗罗多...
这项任务是交给你的,如果你找不到方法,就没有人会找到。
###对我来说,至少在网络堆栈中使用传输层作为策略是有意义的。###
例如,假设你有一个名为connection的类。然后你有一个TCP_conn类和一个UDP_conn类,它们各自定义了数据包、头文件和方法,例如:
- send方法
- TCP的receive方法
- setup方法
然后你像你的示例一样继承:
Template<class Protocol>
class Connection : public Protocol
{
}
例如,假设您有一个Waveform类,用于生成波形。
template <class SamplingPolicy >
class Waveform
;
但是你需要针对128个样本和1024个样本制定政策,你不能在动态分配上执行此操作,因为需要在编译时定义采样率而不是运行时...(在这种情况下用于测试目的)
因此,在每个样本128个点的情况下,政策将如下所示:
class W_128_Samples
{
public:
static const std::size_t components = 2;
static const std::size_t halfcycle_samples = 64;
typedef boost::array< boost::array<int16_t, halfcycle_samples>, components > Wave;
typedef boost::array<int16_t, halfcycle_samples> component;
typedef boost::array< boost::array<int16_t, halfcycle_samples>, components >::iterator iterator;
typedef boost::array< boost::array<int16_t, halfcycle_samples>, components >::const_iterator const_iterator;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
typedef int16_t inner_type;
typedef boost::array<int16_t, components>::size_type size_type;
typedef boost::array<int16_t, components>::iterator inner_iterator;
typedef boost::array<int16_t, components>::const_iterator const_inner_iterator;
inner_iterator begin(iterator Itr);
const_inner_iterator begin(iterator Itr) const;
inner_iterator end(iterator Itr);
const_inner_iterator end(iterator Itr) const;
std::size_t Rows() const;
std::size_t Columns() const;
component& row(size_type const &n);
const component& row(size_type const &n) const;
const Wave& get() const;
Wave& get();
protected:
boost::array< boost::array<int16_t, halfcycle_samples>, components > _wave;
};
而在每个样本1024个点的情况下,策略会变成这样:
class W_1024_Samples
{
public:
static const std::size_t components = 2;
static const std::size_t halfcycle_samples = 512;
typedef boost::array< boost::array<int16_t, halfcycle_samples>, components > Wave;
typedef boost::array<int16_t, halfcycle_samples> component;
typedef boost::array< boost::array<int16_t, halfcycle_samples>, components >::iterator iterator;
typedef boost::array< boost::array<int16_t, halfcycle_samples>, components >::const_iterator const_iterator;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
typedef int16_t inner_type;
typedef boost::array<int16_t, components>::size_type size_type;
typedef boost::array<int16_t, components>::iterator inner_iterator;
typedef boost::array<int16_t, components>::const_iterator const_inner_iterator;
inner_iterator begin(iterator Itr);
const_inner_iterator begin(iterator Itr) const;
inner_iterator end(iterator Itr);
const_inner_iterator end(iterator Itr) const;
std::size_t Rows() const;
std::size_t Columns() const;
component& row(size_type const &n);
const component& row(size_type const &n) const;
const Wave& get() const;
Wave& get();
protected:
boost::array< boost::array<int16_t, halfcycle_samples>, components > _wave;
};
正如你所看到的,事情可以变得任意长。
另一个重要的事情是,我使用组合而不是继承来实现我的策略,这是Alexandrescu在他与Herb Sutter合著的另一本C++指南书中的建议。
带回家的主要信息是:
你需要尽可能地节省代码--你写的越少,你就会获得更多的价值。但这并不意味着它不难。
所以,再次强调,这取决于你的问题。
例如,要使用我的代码,我会执行以下操作:
Waveform<W_128_Samples> w1;
w1.setup(60, 1000);
Waveform<W_1024_Samples> w2;
w2.setup(60, 1000);
其中60为频率,1000为振幅。两者都将返回数组,只是大小不同。
当你绘制它时,1024大小会更加平滑。
这对于我在c++中直接测试与波形相关的事物非常方便,我可以通过添加或减去不同的波形来组装不同的波形。
#优点是什么?#
好吧,设置方法是Waveform类模板定义的。但是数组保持在策略中,并且策略还有数组和数组大小的访问器。此外,您可以为策略扩展功能。
#为什么不使用继承?#
个人偏好和一些基于某些书籍的原因。只要不在基类功能上发疯,就可以使用继承。
#为什么Policy中有这么多方法?#
因为波形本身是私有的,用户可以创建声音,但不能改变它。
#为什么有这么多重载?#
我想能够像Matlab一样在C++中使用我的Waveforms。
#什么是Policy实现可能变得很大?#
假设您正在实现粒子群优化。您在一个模板中编写PSO,该模板接收数据数组并根据其进行问题优化。
但是您的策略负责每个粒子的权重以及如何从N数据结构传递到数据数组中。
因此,在模板管理器中调用设置方法,就像我说的那样,管理器接收一个数组,但它调用策略的一种方法来接收数组。该策略中的方法将矩阵映射到数组或将数据库映射到数组。
所以现在您需要处理类似于策略和权重中的I/O之类的东西。
这可能会变得非常庞大。