I have the following existing classes:
class Gaussian {
public:
virtual Vector get_mean() = 0;
virtual Matrix get_covariance() = 0;
virtual double calculate_likelihood(Vector &data) = 0;
};
class Diagonal_Gaussian : public Gaussian {
public:
virtual Vector get_mean();
virtual Matrix get_covariance();
virtual double calculate_likelihood(Vector &data);
private:
Vector m_mean;
Vector m_covariance;
};
class FullCov_Gaussian : public Gaussian {
public:
virtual Vector get_mean();
virtual Matrix get_covariance();
virtual double calculate_likelihood(Vector &data);
private:
Vector m_mean;
Matrix m_covariance;
};
As you see, the class Gaussian acts as an interface but doesn't have any implementation. This is all working fine.
Now I want to make an class "AdaptedGaussian" where the data vector provided to the calculated_likelihood will be changed before the likelihood is calculated.
Some requirements:
The idea I have now is:
class Adapted_Gaussian : public Gaussian {
private:
Gaussian* m_g;
public:
virtual Vector get_mean() { return m_g->get_mean(); }
virtual Matrix get_covariance() { return m_g->get_covariance(); }
virtual double calculate_likelihood(Vector &data)
{
//do something with data
return g->calculate_likelihood(Vector &data);
}
}
There are maybe some disadvantages:
Am I doing this in the right way? Or are there better methods to implement this?
Is there maybe a good way to standard delegate every non-implemented method to the same named method of m_g?
Looks good, I think this is a pretty classic implementation of the Adapter pattern. Just don't forget to declare a virtual destructor for your Gaussian class. As for the disadvantages.
As you point out writing a lot of basic pass-through functions is tedious and adds an implied maintenance overhead. Also, having a pointer member implies extra (albeit simple) lifetime management issues of the owned pointer. Probably the simplest way to address these issues is to make AdaptedGaussian a template, templated on the specific instance of Gaussian to be adapted.
template<class BaseGaussian> class AdaptedGaussian : public BaseGaussian
{
virtual double calculate_likelihood(Vector &data)
{
// do something with data
return BaseGaussian::calculate_likelihood(Vector &data);
}
};
This does rely on all adapted instances of Gaussian being default constructible, or at least conforming to a common constructor signature.
If you want to construct an AdaptedGaussian from an existing XXXGaussian, then so long as the XXXGaussian is itself copyable you can add a suitable constructor:
template<class BaseGaussian> class AdaptedGaussian : public BaseGaussian
{
public:
AdaptedGaussian(const BaseGaussian& other) : BaseGaussian(other)
{
}
// ...
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With