笔记:Gof设计模式--Visitor

本文介绍了一种软件设计模式——访客模式。该模式允许在不修改对象结构的情况下定义新的操作,适用于需要对不同类型的对象执行多种操作且不想污染这些对象本身的场景。文中详细解释了访客模式的应用场景、结构,并通过示例代码展示了如何实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、意图

  Represent an operation to be performed on the elements of an objectstructure. Visitor lets you define a new operation without changing theclasses of the elements on which it operates.

2、适应性

  Use the Visitor pattern when

  •  an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.

  •  many distinct and unrelated operations need to be performed on objectsin an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operationstogether by defining them in one class. When the object structure isshared by many applications, use Visitor to put operations in just hose applications thatneed them.

  •  the classes defining the object structure rarely change, but you oftenwant to define new operations over the structure. Changing the objectstructure classes requires redefining the interface to all visitors,which is potentially costly. If the object structure classes changeoften, then it's probably better to define the operations in those classes.

3、结构

4、示例代码

  Here again is the Equipment class from Composite (183). We've augmented it with anAccept operation to let it work with a visitor.

class Equipment { 
public: 
  virtual ~Equipment();             
 
  const char* Name() { return _name; }   
  virtual Watt Power(); 
  virtual Currency NetPrice(); 
  virtual Currency DiscountPrice(); 
 
  virtual void Accept(EquipmentVisitor&); 
protected: 
  Equipment(const char*); 
private: 
  const char* _name; 
}; 


  The abstract class for all visitors of equipment has a virtualfunction for each subclass of equipment, as shown next. All of thevirtual functions do nothing by default.

class EquipmentVisitor { 
public: 
  virtual ~EquipmentVisitor(); 
 
  virtual void VisitFloppyDisk(FloppyDisk*); 
  virtual void VisitCard(Card*); 
  virtual void VisitChassis(Chassis*); 
  virtual void VisitBus(Bus*); 
 
  // and so on for other concrete subclasses of Equipment 
protected: 
  EquipmentVisitor(); 
}; 


  Equipment subclasses define Accept inbasically the same way: It calls theEquipmentVisitor operation that corresponds to the classthat received the Accept request, like this:

void FloppyDisk::Accept (EquipmentVisitor& visitor) { 
  visitor.VisitFloppyDisk(this); 
} 

//  Chassis::Accept could traverseall the parts in the chassis as follows:
void Chassis::Accept (EquipmentVisitor& visitor) { 
  for ( 
   ListIterator i(_parts); 
   !i.IsDone(); 
   i.Next() 
   ) { 
    i.CurrentItem()->Accept(visitor); 
  } 
  visitor.VisitChassis(this); 
} 


  Subclasses of EquipmentVisitor define particular algorithmsover the equipment structure.

// PricingVisitor will compute the total cost of all nodes in theequipment structure. 
class PricingVisitor : public EquipmentVisitor { 
public: 
  PricingVisitor(); 
 
  Currency& GetTotalPrice(); 
 
  virtual void VisitFloppyDisk(FloppyDisk*); 
  virtual void VisitCard(Card*); 
  virtual void VisitChassis(Chassis*); 
  virtual void VisitBus(Bus*); 
  // ... 
private: 
  Currency _total; 
}; 
 
void PricingVisitor::VisitFloppyDisk (FloppyDisk* e) { 
  _total += e->NetPrice(); 
} 
 
void PricingVisitor::VisitChassis (Chassis* e) { 
   _total += e->DiscountPrice(); 
} 


// The InventoryVisitor accumulates the totals for each type ofequipment in the object structure.
class InventoryVisitor : public EquipmentVisitor { 
public: 
  InventoryVisitor(); 
 
  Inventory& GetInventory(); 
 
  virtual void VisitFloppyDisk(FloppyDisk*); 
  virtual void VisitCard(Card*); 
  virtual void VisitChassis(Chassis*); 
  virtual void VisitBus(Bus*); 
  // ... 
private: 
  Inventory _inventory; 
}; 

void InventoryVisitor::VisitFloppyDisk (FloppyDisk* e) { 
  _inventory.Accumulate(e); 
} 
 
void InventoryVisitor::VisitChassis (Chassis* e) { 
  _inventory.Accumulate(e); 
} 


  Here's how we can use an InventoryVisitor on anequipment structure:

Equipment* component; 
InventoryVisitor visitor; 
 
component->Accept(visitor); 
cout << "Inventory " 
 << component->Name() 
 << visitor.GetInventory(); 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值