使用装饰器模式C ++时,抽象基类应该有或没有数据成员

时间:2014-01-14 01:36:49

标签: c++ inheritance decorator

以前有些帖子曾询问/讨论是否在隐式基类中包含私有数据成员。我想在这个结合装饰模式的具体例子中探讨这个。

当我实施蒙特卡罗图书馆为金融衍生品定价时,我遇到了这个问题。 随机正常数生成器是蒙特卡罗定价库的重要组成部分。您可以选择如何从随机统一数字生成器开始定义常规变量,例如:您可以使用Box-Muller方法或反向累积正态函数从均匀变量中获取正态变量。

您想要一个允许随机获得一个或多个随机变量的公共接口:例如getRandomNormal()和getRamdomNormals()。所以我们来看一个抽象基类RandomNormalGenerator。您希望将随机法线存储在向量中,因为您希望在子类中对其进行一些操作。我还决定实施反理论抽样,其中我在从抽象基础派生的类中取存储的随机法线并反转这些随机法线的符号(反对抽样原理)。我的头文件看起来像这样

#ifndef RANDOMNORMALGENERATOR_H_
#define RANDOMNORMALGENERATOR_H_

#include "UniformBridge.h"
#include <memory>

class RandomNormalGenerator {
public:
    RandomNormalGenerator();
    RandomNormalGenerator(const UniformBridge& uniform_bridge);
    void SetSeed(long seed);

    virtual double getRandomNormal() = 0;
    virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:
    UniformBridge m_UBridge; // Need access to m_UBridge in derived classes.
    std::vector<double> m_Normals; //Need access to m_Normals in derived classes.
private:
};

class BoxMullerGenerator: public RandomNormalGenerator {
public:
    BoxMullerGenerator();
    BoxMullerGenerator(const UniformBridge& uniform_bridge);
    virtual double getRandomNormal();
protected:
private:
    double m_Cached_value;
    bool m_Cached_flag;
};

class AntitheticGenerator: public RandomNormalGenerator {
public:
    AntitheticGenerator(std::unique_ptr<RandomNormalGenerator> generator);
    virtual double getRandomNormal();

    // getRandomNormals will generate in first go, non-antithetic sampled samples,
    // when called for second time it will generate antithetic samples.
    virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:

private:
    AntitheticGenerator(const AntitheticGenerator&);
    AntitheticGenerator& operator=(const AntitheticGenerator&);

private:
    std::unique_ptr<RandomNormalGenerator> m_RandNormGenerator;
};

#endif /* RANDOMNORMALGENERATOR_H_ */

请注意,AntitheticGenerator使用它从抽象基类继承的装饰器模式,并且具有指向此抽象基类的指针(基类对象周围的包装器也可以)。

AntitheticGenerator将采用一个指针,例如对于BoxMuller并使用BoxMuller生成随机法线,它将使用存储在BoxMuller的m_Normals中的随机法线(装饰它们)。具体地说,它将反转这些值的符号(如果BoxMuller中有缓存的向量)并将它们存储在自己的m_Normals(AntitheticGenerator中的m_Normals)中。这里将m_Normals向量委托给抽象基类是非常有用的,因此不需要在子类中重复。然而,基类中的UniformBridge mUBridge(统一随机生成器的桥梁)并不是一个好主意。 AntitheticGenerator不需要自己的统一随机生成器,因为它将使用BoxMuller中的那个......事实上,反对生成器中的mUbridge从未使用过。

所以纠正后的代码应该是这样的。

#ifndef RANDOMNORMALGENERATOR_H_
#define RANDOMNORMALGENERATOR_H_

#include "UniformBridge.h"
#include <memory>

class RandomNormalGenerator {
public:
    RandomNormalGenerator();
    void SetSeed(long seed);

    virtual double getRandomNormal() = 0;
    virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:
    std::vector<double> m_Normals; //Need access to m_Normals in derived classes.
private:
};

class BoxMullerGenerator: public RandomNormalGenerator {
public:
    BoxMullerGenerator();
    BoxMullerGenerator(const UniformBridge& uniform_bridge);
    virtual double getRandomNormal();
protected:
private:
    double m_Cached_value;
    bool m_Cached_flag;
    UniformBridge m_UBridge;
};

class AntitheticGenerator: public RandomNormalGenerator {
public:
    AntitheticGenerator(std::unique_ptr<RandomNormalGenerator> generator);
    virtual double getRandomNormal();

    // getRandomNormals will generate in first go, non-antithetic sampled samples,
    // when called for second time it will generate antithetic samples.
    virtual const std::vector<double>& getRandomNormals(size_t dimension);
protected:

private:
    AntitheticGenerator(const AntitheticGenerator&);
    AntitheticGenerator& operator=(const AntitheticGenerator&);

private:
    std::unique_ptr<RandomNormalGenerator> m_RandNormGenerator;
};

#endif /* RANDOMNORMALGENERATOR_H_ */

使用装饰器模式生成随机法线的结论,它对定义基类中法线的存储很有用,但是应该将统一随机生成器的存储委托给子类(装饰类不是需要它自己的。)

0 个答案:

没有答案