class DistanceBase { public: virtual ~DistanceBase() {} virtual double distance(const RD_Vector&) = 0; };
class L1Distance : public DistanceBase { virtual double distance(const RD_Vector& v) { double sum=0.0; for (int i=1;i<=v.nelems();++i) sum+=fabs(v); return sum; } }; class L2Distance : public DistanceBase { virtual double distance(const RD_Vector& v) { return sqrt(dot(v,v)); } };
Client:
class NearestNeighbour { private: DistanceBase* _d; public: NearestNeighbour(DistanceBase& d) : _d(&d) {} int nearest(const RD_Array<RD_Vector>& data, const RD_Vector& v); // Uses _d->distance(dv) };
We can change the functionality without changing the implementation:
L1Distance distance1; L2Distance distance2; NearestNeighbour nearest1(distance1); // Uses L1 metric NearestNeighbour nearest2(distance2); // Uses L2 metric