ch0877翻译了一篇名叫《分析模式-计量》的文章(http://www.csdn.net/Develop/article/14/14449.shtm),很不错。我就试着用C++实现了一下。
以下是源代码:
#ifndef _QUANTITY_H_#define _QUANTITY_H_
#include <crtdbg.h>
template<typename ValueType>class Quantity{public: template<typename UnitType>Weight(const ValueType & amount, const UnitType & unit) : m_amount(amount), m_unit(new unit_wrap<UnitType, ValueType>(unit)) { } ~Quantity() { delete m_unit; } Quantity(const Quantity & other) : m_amount(other.m_amount), m_unit(other.m_unit ? other.m_unit->clone() : 0) { } Quantity & operator=(const Quantity & rhs) { if(&rhs == this) return *this; m_amount = rhs.m_amount; delete m_unit; m_unit = rhs.m_unit ? rhs.m_unit->clone() : 0; return *this; } template<typename UnitType> void convert(const UnitType & new_unit) { _ASSERT(m_unit); m_amount = m_unit->to_standard(m_amount); delete m_unit; m_unit = new unit_wrap<UnitType, double>(new_unit); m_amount = m_unit->from_standard(m_amount); } Quantity & operator+=(const Quantity & rhs) { _ASSERT(m_unit); _ASSERT(rhs.m_unit); m_amount = m_unit->from_standard( m_unit->to_standard(m_amount) + rhs.m_unit->to_standard(rhs.m_amount) ); return *this; } Quantity & operator-=(const Quantity & rhs) { _ASSERT(m_unit); _ASSERT(rhs.m_unit); m_amount = m_unit->from_standard( m_unit->to_standard(m_amount) - rhs.m_unit->to_standard(rhs.m_amount) ); return *this; } bool operator==(const Quantity & rhs) { _ASSERT(m_unit); _ASSERT(rhs.m_unit); return equal(m_unit->to_standard(m_amount) , rhs.m_unit->to_standard(rhs.m_amount) ); } bool operator>(const Quantity & rhs) { _ASSERT(m_unit); _ASSERT(rhs.m_unit); return (m_unit->to_standard(m_amount) > rhs.m_unit->to_standard(rhs.m_amount) ); }
private: template<typename T>bool equal(const T & l, const T & r) {return (l == r);} template<>bool equal<double>(const double & l, const double & r) { static double precision = 0.000000001; return (l - r < precision); }
private: template<typename ValueType> class unit_base { public: virtual ~unit_base() { } public: virtual unit_base * clone() const = 0; virtual ValueType to_standard(const ValueType & val) const = 0; virtual ValueType from_standard(const ValueType & val) const = 0; }; template<typename UnitType, typename ValueType> class unit_wrap : public unit_base<ValueType> { public: unit_wrap(const UnitType & unit) : m_content(unit) { } public: virtual unit_base<ValueType> * clone() const { return new unit_wrap(m_content); } virtual ValueType to_standard(const ValueType & val) const { return m_content.to_standard(val); } virtual ValueType from_standard(const ValueType & val) const { return m_content.from_standard(val); } private: UnitType m_content; };
private: ValueType m_amount; unit_base<ValueType> * m_unit;};
template<typename ValueType>Quantity<ValueType> inline _cdecl operator+(const Quantity<ValueType> & a, const Quantity<ValueType> & b){return (Quantity<ValueType>(a)+=b);}
template<typename ValueType>Quantity<ValueType> inline _cdecl operator-(const Quantity<ValueType> & a, const Quantity<ValueType> & b){return (Quantity<ValueType>(a)-=b);}
#endif /* _QUANTITY_H_ */
以下是示例代码:
typedef Quantity<double> Weight;class UNIT_KG{public: double to_standard(double val) const {return val;} double from_standard(double val) const {return val;}};
class UNIT_G{public: double to_standard(double val) const {return val/1000.0;} double from_standard(double val) const {return val*1000.0;}};
UNIT_KG _kg;UNIT_G _g;
Weight w1(1.0, _kg); Weight w2(1.0, _g); w1.convert(_g); w1.convert(_kg); w2 = w1; Weight w10(1.0, _kg); Weight w20(500.0, _g); w10 += w20; Weight w30(w10 + w20); bool b = (w10 == w20); b = (w30 > w10);