C++ 与访问者设计模式实现相关的问题
根据我当前的需求,我已经实现了访客模式,我们有以下几个不同方面: 1> 与GoF手册中的经典示例不同,设备的子类不是扁平的。换句话说,子类都在层次结构中 例如: //平坦的 设备A:公共设备{} 设备B:公共设备{} 设备C:公共设备{}C++ 与访问者设计模式实现相关的问题,c++,design-patterns,visitor-pattern,C++,Design Patterns,Visitor Pattern,根据我当前的需求,我已经实现了访客模式,我们有以下几个不同方面: 1> 与GoF手册中的经典示例不同,设备的子类不是扁平的。换句话说,子类都在层次结构中 例如: //平坦的 设备A:公共设备{} 设备B:公共设备{} 设备C:公共设备{} //hierarchy EquipmentA : public Equipment {} EquipmentB : public EquipmentA {} EquipmentC : public EquipmentB {} 2> 子类有一些特殊的函数,这些
//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>我应该关注我标记为“备注”的区块吗
i、 e.如果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;
}
//////////////////////////////////////////////////////////////////////////
类软盘;
类SpecialFloppyDisk;
班级设备访客
{
公众:
虚拟~EquipmentVisitor(){}
//根据设备的不同子类修改设备
虚拟无效VisitFloppyDisk(FloppyDisk&)=0;
虚拟无效访问SpecialFloppyDisk(SpecialFloppyDisk&)=0;
int GetTotalPrice()常量{return m_iTotalPrice;}
受保护的:
国际电信价格;
受保护的:
设备访问者(){}
};
//////////////////////////////////////////////////////////////////////////
一流设备{
公众:
虚拟~Equipment(){}
//退还设备的价格
虚拟整数GetPrice()常量=0;
虚拟无效接受(设备访问者&)=0;
受保护的:
设备(){}
};
//////////////////////////////////////////////////////////////////////////
磁盘类:公共设备
{
公众:
//退还设备的价格
虚拟int GetPrice()常量{return 100;}
int GetFactorRate()常量{return 2;}//x 2
虚拟无效接受(设备访问者&e){e.VisitFloppyDisk(*this);}
};
//////////////////////////////////////////////////////////////////////////
类SpecialFloppyDisk:公共FloppyDisk
{
公众:
虚拟std::string GetName()常量{返回std::string(“总线”);}
//退还设备的价格
虚拟int GetPrice()常量{return 20000;}
int getAmplicateRate()常量{return 11;}//x 11
虚拟无效接受(设备访客和设备)
{
e、 访问SpecialFloppyDisk(*此项);
//注意:如果意外调用以下函数,那么它将引入
//隐藏的虫子!!!!
//e.VisitFloppyDisk(*本文件);
}
};
//////////////////////////////////////////////////////////////////////////
类PricingVisitor:公共设备访客
{
公众:
虚拟无效访问FloppyDisk(FloppyDisk&e)
{m_iTotalPrice=e.GetPrice()*e.GetFactorRate();}
虚拟无效访问专用FloppyDisk(专用FloppyDisk&e)
{m_iTotalPrice=e.GetPrice()*e.GetRate();}
};
//////////////////////////////////////////////////////////////////////////
int _tmain(int argc,_TCHAR*argv[]
{
PricingVisitor PricingVisitor;
SpecialFloppyDisk SpecialFloppyDisk;
FloppyDisk-FloppyDisk;
接受(pricingVisitor);
//输出:pricingVisitor.GetTotalPrice():200
//即100 x 2
std::coutQ1:有问题吗?有。设计问题:
EquipmentVisitor
不应具有GetTotalPrice()/m_iTotalPrice
。它应该是纯类,仅包含访问内容。Visitor模式主要用于向类族(在本例中为设备)添加新功能不修改这些类。如果添加其他访问者-那么它很可能对设备价格不感兴趣。如果它对定价感兴趣-那么它应该派生自PricingVisitor
把价格的东西移到PricingVisitor,这是合适的地方
不要为不同的访问
方法指定不同的名称。编译器将根据*此
类型在接受
中选择正确的方法
Q2:如果SpecialFloppyDisk调用VisitFloppyDisk而不是SpecialVisitFloppyDisk怎么办:
Q1.3中已经提到-不要使用不同的名称-这样可以避免问题
class EquipmentVisitor
{
public:
virtual ~EquipmentVisitor() {}
virtual void Visit(FloppyDisk&) = 0;
virtual void Visit(SpecialFloppyDisk&) = 0;
};
Q1:有问题吗?有。设计问题:
EquipmentVisitor
不应具有GetTotalPrice()/m_iTotalPrice
。它应该是纯类,仅包含访问内容。Visitor模式主要用于向类族(在本例中为设备)添加新功能不修改这些类。如果添加其他访问者-那么它很可能对设备价格不感兴趣。如果它对定价感兴趣-那么它应该派生自PricingVisitor
把价格的东西移到PricingVisitor,这是合适的地方
不要为不同的访问
方法指定不同的名称。编译器将根据*此
类型在接受
中选择正确的方法
Q2:如果SpecialFloppyDisk调用VisitFloppyDisk而不是SpecialVisitFloppyDisk怎么办:
Q1.3中已经提到-不要使用不同的名称-这样可以避免问题
class EquipmentVisitor
{
public:
virtual ~EquipmentVisitor() {}
virtual void Visit(FloppyDisk&) = 0;
virtual void Visit(SpecialFloppyDisk&) = 0;
};
这可能是在代码审查上,那是很多代码。这可能是在代码审查上,那是很多代码。