根据我目前的要求,我实施了访客模式,我们有以下不同方面:
1>与GoF书中所示的经典示例不同,设备的子类不是平坦的。换句话说,子类都在层次结构中。
例如: //平面 设备A:公共设备{} 设备B:公共设备{} EquipmentC:公共设备{}
//hierarchy
EquipmentA : public Equipment {}
EquipmentB : public EquipmentA {}
EquipmentC : public EquipmentB {}
2 - ;子类有一些专门的函数,它们不是基类中定义的虚函数。 例如:
`EquipmentA` may define a function called `GetFactorRate`
`EquipmentB` may define a function called `GetAmplifyRate`
记住所有这些,这是我的代码。
问题1 >代码有问题吗?
问题2 >我是否应该关注我标记为"注意"
即如果SpecialFloppyDisk
拨打VisitFloppyDisk
而不是SpecialVisitFloppyDisk
,该怎么办?
我认为良好的代码设计方式使其难以犯错误。但我不确定这种情况是否适用于此。
//////////////////////////////////////////////////////////////////////////
class FloppyDisk;
class SpecialFloppyDisk;
class EquipmentVisitor
{
public:
virtual ~EquipmentVisitor() {}
// modify Equipment based on different subclass of Equipment
virtual void VisitFloppyDisk(FloppyDisk&) = 0;
virtual void VisitSpecialFloppyDisk(SpecialFloppyDisk&) = 0;
int GetTotalPrice() const { return m_iTotalPrice; }
protected:
int m_iTotalPrice;
protected:
EquipmentVisitor() {}
};
//////////////////////////////////////////////////////////////////////////
class Equipment {
public:
virtual ~Equipment() {}
// return the price of the Equipment
virtual int GetPrice() const = 0;
virtual void Accept(EquipmentVisitor&) = 0;
protected:
Equipment() {}
};
//////////////////////////////////////////////////////////////////////////
class FloppyDisk : public Equipment
{
public:
// return the price of the Equipment
virtual int GetPrice() const {return 100;}
int GetFactorRate() const {return 2; } // x 2
virtual void Accept(EquipmentVisitor& e){e.VisitFloppyDisk(*this);}
};
//////////////////////////////////////////////////////////////////////////
class SpecialFloppyDisk : public FloppyDisk
{
public:
virtual std::string GetName() const {return std::string("Bus");}
// return the price of the Equipment
virtual int GetPrice() const {return 20000;}
int GetAmplifyRate() const {return 11; }// x 11
virtual void Accept(EquipmentVisitor& e)
{
e.VisitSpecialFloppyDisk(*this);
// Note: if called the following function by accident, then it introduces
// hidden bugs!!!!
// e.VisitFloppyDisk(*this);
}
};
//////////////////////////////////////////////////////////////////////////
class PricingVisitor : public EquipmentVisitor
{
public:
virtual void VisitFloppyDisk(FloppyDisk& e)
{m_iTotalPrice = e.GetPrice() * e.GetFactorRate();}
virtual void VisitSpecialFloppyDisk(SpecialFloppyDisk& e)
{ m_iTotalPrice = e.GetPrice() * e.GetAmplifyRate(); }
};
//////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
PricingVisitor pricingVisitor;
SpecialFloppyDisk specialFloppyDisk;
FloppyDisk floppyDisk;
floppyDisk.Accept(pricingVisitor);
// output: pricingVisitor.GetTotalPrice(): 200
// i.e. 100 x 2
std::cout << "pricingVisitor.GetTotalPrice(): " << pricingVisitor.GetTotalPrice() << std::endl;
// output: pricingVisitor.GetTotalPrice(): 220000
// i.e. 20000 x 11
specialFloppyDisk.Accept(pricingVisitor);
std::cout << "pricingVisitor.GetTotalPrice(): " << pricingVisitor.GetTotalPrice() << std::endl;
return 0;
}
答案 0 :(得分:0)
Q1:有什么问题吗?对,他们是。设计问题:
EquipmentVisitor
不得有GetTotalPrice()/m_iTotalPrice
。它应该是仅包含Visit内容的纯类。访问者模式主要用于向类族(在本例中为设备)添加新功能,而无需修改这些类。如果添加其他访客 - 那么它很可能对设备价格不感兴趣。如果它对定价感兴趣 - 那么它应该来自PricingVisitor
。 Visit
方法创建不同的名称。编译器将根据Accept
类型在*this
中选择正确的方法。Q2:如果SpecialFloppyDisk调用VisitFloppyDisk而不是SpecialVisitFloppyDisk,那该怎么办:
在Q1.3中已经提到过 - 不要使用不同的名称 - 这样可以避免出现问题。
class EquipmentVisitor
{
public:
virtual ~EquipmentVisitor() {}
virtual void Visit(FloppyDisk&) = 0;
virtual void Visit(SpecialFloppyDisk&) = 0;
};