我对特定类型的对象有不同的访问者。我在实现可用于所有类型的通用接口时遇到问题。在这种情况下使用的最佳架构是什么?我提出了3种不同的解决方案,但是对我来说它们看起来都很丑陋:(为了简单起见,虚拟析构函数等一些东西被删除了)
class IObject {
virtual void Accept(IVisitor& visior) = 0;
};
class Text: IObject {
void Accept(IVisitor& visitor) {
visitor.Visit(*this);
}
};
class Image: IObject {
void Accept(IVisitor& visitor) {
visitor.Visit(*this);
}
};
class IVisitor {
virtual void Visit(Text& text) = 0;
virtual void Visit(Image& image) = 0;
};
class TextVisitor: IVisitor {
void Visit(Text& text) {
// Do some stuff with text
}
void Visit(Image& image) {
// Image not supported, throw exception
}
};
OR
class IObject {};
class Text: IObject {};
class Image: IObject {};
class IVisitor {
virtual void Visit(IObject& object) = 0;
};
class TextVisitor: IVisitor {
void Visit(IObject& object) {
Text& text = dynamic_cast<Text&>(object);
// Do some stuff with text
}
};
OR
template <typename T>
class IVisitor {
virtual void Visit(T& object) = 0;
};
class TextVisitor: IVisitor<Text> {
void Visit(Text& text) {
// Do some stuff
}
};
class ImageVisitor: IVisitor<Image> {
void Visit(Image& image) {
// Do some stuff
}
};
class ITextImagelVisitor: IVisitor<Text>, IVisitor<Image> {};
class VisitorDispatcher: ITextImageVisitor {
void Visit(Text& text) {
text_visitor_->Visit(text);
}
void Visit(Image& image) {
image_visitor_->Visit(image);
}
std::shared_ptr<IVisitor<Text>> text_visitor_;
std::shared_ptr<IVisitor<Image>> image_visitor_;
};
class IObject {
virtual void Accept(ITextImageVisitor& visior) = 0;
};
class Text: IObject {
void Accept(ITextImageVisitor& visitor) {
visitor.Visit(*this);
}
};
class Image: IObject {
void Accept(ITextImageVisitor& visitor) {
visitor.Visit(*this);
}
};
答案 0 :(得分:2)
答案显然取决于你在这里实现的目的。 访问者模式用于处理组合对象,例如,树和自称在该组成的子对象上。在您的示例中,这将是包含文本和图像的文本,其中包含文本和图像...这显然似乎没有多大意义,所以如果您 实际上使用文本和图像,访客可能不是你所需要的,你应该提供一些关于你想要达到的目标的更多信息。
使用不同的代码:
dynamic_cast
,dynamic_cast
对你没有多大帮助。如果您只想支持一种类型的对象,则不需要访问者。VisitorDispatcher
继承了Visitor<Text>
的,还包含 Visitor<Text>
。这充其量只是一种奇怪的设计。答案 1 :(得分:0)
请注意您的Visitor
类如何需要有关Object
的派生类的信息。您想要进行多态,但却无法为每个新派生的Object
创建单独的访问者。为了完成这项工作,您需要让Object
更加灵活。我假设您正在尝试创建某种在屏幕上绘制Object
的机制,因此每个对象还需要virtual int width() = 0
和virtual int height() = 0
这些由派生器实现。那么virtual void draw() = 0
的抽象方法Object
也是必要的。这样,您不需要class TextVisitor
,也不需要class ImageVisitor
,Visitor
只需在object->draw()
访问的Object
内致电{{1}}。