设计模式学习笔记(二十五)——Visitor访问者

本文介绍了一种设计模式——访问者模式,通过实例演示了如何在不改变对象结构的情况下为对象集合添加新的操作。该模式利用双分派机制,适用于无法直接修改对象结构的情况。

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

二十三、Visitor(访问者)

情景举例:

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

代码示例:

/* 被访问类的父类,注意其中虚拟函数Accept是提供给访问者的接口
*/
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;
};
/* 访问者的父类,多个虚拟函数让子类可以自定义其行为(仅行为)
*/
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();
};
/* 下面几个是被访问者的具体类
*/
class FloppyDisk : public Equipment {
  public:
    virtual void Accept(EquipmentVisitor&);
};
/* accept里调用了访问者的某个虚拟函数
*/
void FloppyDisk::Accept (EquipmentVisitor& visitor) {
   visitor.VisitFloppyDisk(this);
}
/* 另一个具体类的例子
*/
class CompositeEquipment : public Equipment {
  public:
    virtual void Accept(EquipmentVisitor&);
};
 
class Chassis : public CompositeEquipment {
  public:
    virtual void Accept(EquipmentVisitor&);
    List<Equipment*>* _parts;
};
/*
*/
void Chassis::Accept (EquipmentVisitor& visitor) {
    for (
        ListIterator<Equipment*> i(_parts);
        !i.IsDone();
        i.Next()
    ) {
        i.CurrentItem()->Accept(visitor);
    }
    visitor.VisitChassis(this);
}
/* 访问者类的具体类,定义了父类的虚拟函数的实现
*/
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();
}
/* 另一个具体类
*/
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);
}
/* 主程序中展示了使用的方法
*/
ostream&  operator<<(ostream&, const Inventory&);
void dummy() {
/*
*/
Equipment* component;
InventoryVisitor visitor;
 
component->Accept(visitor);
cout << "Inventory "
     << component->Name()
     << visitor.GetInventory();
/*
*/
}

个人理解:

简单来讲,visitor模式是一个双分派的实现方法,即根据两种类型来实现多态。C++中只能由一种类型来实现多态,但用visitor模式就可以做到。在MeyerEffictive C++中对这种方法有更具体的介绍。这种模式是在于被访问类不方便修改或者无法访问代码的时候适用的(但被访问类至少要提供给访问类一个接口,如accept

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值