2012-08-02 34 views
2

的問題,我已經實現了訪問者模式,我們有一些不同的方面如下:與執行有關的Visitor設計模式基於我目前的需求

1>從GoF的書所示的典型的例子不同的是,子類的設備沒有攤鋪。換句話說,子類都在層次結構中。

例如: //平 EquipmentA:公共設備{} EquipmentB:公共設備{} 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; 
} 
+1

這應該可能是代碼評論,這是很多代碼。 – 2012-08-02 16:04:53

回答

0

Q1:是否有問題?對,他們是。設計問題:

  1. EquipmentVisitor不得有GetTotalPrice()/m_iTotalPrice。它應該是純粹的類只包含訪問的東西。訪問者模式主要用於向類族(在這種情況下爲設備)添加新功能而不修改這些類。如果添加其他訪問者 - 那麼它很可能對設備價格不感興趣。如果它對價格感興趣 - 那麼它應該來自PricingVisitor
  2. 移動價格的東西到PricingVisitor,這是它的正確的地方。
  3. 不要爲不同的Visit方法創建不同的名稱。編譯器將基於*this類型在Accept中選擇正確的方法。

Q2:如果SpecialFloppyDisk稱VisitFloppyDisk代替SpecialVisitFloppyDisk:

在Q1.3已經提到 - 不要使用不同的名字 - 這樣你避免這些問題。

class EquipmentVisitor 
{ 
public: 
    virtual ~EquipmentVisitor() {}  
    virtual void Visit(FloppyDisk&) = 0; 
    virtual void Visit(SpecialFloppyDisk&) = 0; 
};