我一直在阅读Andrei Alexandrescu现代C ++设计的书。我有一个关于将类分解为策略的问题。
基本上什么是一个好的政策规模?大多数示例显示了诸如构造,破坏,螺纹安全等部件。简单地说是小政策:)。
如果我想创建一个文件io类,将文件类型作为策略,例如
,该怎么办?struct XX_Type
{
void AsyncRead(callback c);
void* Write(const uint8* image);
}
struct YY_Type
{
void AsyncRead(callback c);
void* Write(const uint8*, image, uint32 offset);
};
template<class FileType = XX_Type>
class File : public FileType
{
virtual void OnDataRead(const uint8*, uint32 size) = 0;
...
};
想法是从文件继承并创建一个不同的模板,以后可以在需要时生成。这是否适合策略,或者我应该将文件句柄传递给全局静态函数,还是应该为每种类型的文件创建一个类?我想确保用户错误很少:)并且策略似乎不易出错。
编辑:
感谢@Claudiordgz提供了一个很好的不确定答案
举另一个例子是采用网络方法。
UPD和TCP非常相似,但同时又非常不同。它们都需要一个套接字,但一个是无连接的,另一个是面向连接的。但从逻辑上讲,它们仍然是传输的一部分,如果我想创建一个更高级别的抽象,说一个应用层协议,所以采取@Claudiordgz它至少对我来说是有意义的使用传输层作为一个政策,因为它放在网络堆栈上。
答案 0 :(得分:18)
策略是一种巧妙的切换机制,它们用于以下任何一种:
你可以采取任何你刚才所说的方式,这里有各自的优点/缺点:
根据您的算法,run方法可能会扩展到数千行代码。
&#34;大多数示例都显示了构造,破坏,线程安全等部分。简单地说是小政策&#34;,这是因为它们是小例子,政策只能扩展到你的想象力,记住你是程序员,你把代码带到没有人做过的高度。如果你不这样做,没有人愿意。
还记得佛罗多...... 此任务是由您指定的,如果您找不到方法,则没有人愿意。
比如说,你有一个名为连接的类。然后你有一个类TCP_conn和类UDP_conn,每个都定义数据包,标题和方法,例如:
然后你继承了你的例子:
Template<class Protocol>
class Connection : public Protocol
{
// your inherited methods would be here
// just define connect or something
}
例如...... 我们假设您有一个生成波形的波形类
template <class SamplingPolicy >
class Waveform
{
public:
typedef typename SamplingPolicy::iterator iterator;
typedef typename SamplingPolicy::const_iterator const_iterator;
typedef typename SamplingPolicy::inner_iterator inner_iterator;
typedef typename SamplingPolicy::const_inner_iterator const_inner_iterator;
typedef typename SamplingPolicy::size_type size_type;
typedef typename SamplingPolicy::component component;
typedef typename SamplingPolicy::Wave Wave;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
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;
const typename SamplingPolicy::Wave& get() const;
typename SamplingPolicy::Wave& get();
typename SamplingPolicy::component& row(size_type const &n);
const typename SamplingPolicy::component& row(size_type const &n) const;
Waveform();
~Waveform();
template <class Tx, class Ty>
void setup(Tx const &frequency, Ty const &litude);
template <class T>
double Omega(T const &frequency);
Waveform& operator=(Waveform const &rhWave);
Waveform& operator+=(Waveform const &rhWave);
Waveform& operator*=(Waveform const &rhWave);
Waveform& operator-=(Waveform const &rhWave);
Waveform& operator/=(Waveform const &rhWave);
template<class T>
Waveform& operator=(T const &number);
template<class T>
Waveform& operator+=(T const &number);
template<class T>
Waveform& operator*=(T const &number);
template<class T>
Waveform& operator-=(T const &number);
template<class T>
Waveform& operator/=(T const &number);
Waveform operator+(Waveform const &rhWave) const;
Waveform operator-(Waveform const &rhWave) const;
template<class T>
Waveform operator+(T const &number) const;
template<class T>
Waveform operator-(T const &number) const;
Waveform operator/(Waveform const &rhWave) const;
template<class T>
Waveform operator/(T const &number) const;
Waveform operator*(Waveform const &rhWave) const;
template<class T>
Waveform operator*(T const &number) const;
void PrintToConsole(std::size_t columns);
void PrintToFile(std::string const &filename,
std::size_t columns);
protected:
SamplingPolicy _samples;
double _frequency;
double _amplitude;
std::string _frequencyString;
std::string _amplitudeString;
std::map<int,double> _SampleTimes;
private:
bool ValidateSizes(Waveform const &rhWaveform) const;
void print(std::size_t const &columns,
std::ostream &output);
};
但是您需要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类模板上定义的。但是数组保留在策略中,以及数组的访问器和数组的大小。此外,您还可以扩展策略的功能。
个人偏好以及基于某些书籍的其他一些原因。只要你不对基类功能发疯,就可以使用继承。
因为波形本身是私有的,所以用户可以创建声音,但不能改变声音。
我希望能够像Matlab一样使用我的Waveforms,只能在C ++中使用。
假设您正在实施粒子群优化。您可以在接收数据数组的模板中对PSO进行编码,并根据它来优化您的问题。
但是您的策略负责每个粒子的权重,以及如何从N数据结构传递到数据数组。
所以你在模板管理器中调用setup,就像我说管理器收到一个数组,但是它调用了一个接收数组的策略方法。策略中的此方法将矩阵映射到数组中,或将数据库映射到数组中。
所以现在你需要像策略和权重中的I / O那样进行处理。
它可能变得巨大。