C++ 对称访问者模式

C++ 对称访问者模式,c++,oop,design-patterns,visitor,C++,Oop,Design Patterns,Visitor,我正在使用访问者模式定义一些类上的一组操作。 有些操作是可交换的,因此我在访问者模式代码中得到了重复。 假设我有类A B C和运算:A*A,A*B,A*C,B*A,B*B,B*C,C*A,C*B,C*C。 A*A、B*B、C*C是唯一的。 A*B、B*A和朋友将有代码复制 我可以实现A*B,并调用B*A调用A*B,但我最终会问自己:我在哪个文件中实现了A和B之间的操作,是在A还是在B中?(大约有6节课,所以我会问很多这个问题。15对可能的操作) 将来有人在执行新操作时可能会无限循环a*B调用B*

我正在使用访问者模式定义一些类上的一组操作。
有些操作是可交换的,因此我在访问者模式代码中得到了重复。
假设我有类A B C和运算:A*A,A*B,A*C,B*A,B*B,B*C,C*A,C*B,C*C。
A*A、B*B、C*C是唯一的。
A*B、B*A和朋友将有代码复制 我可以实现A*B,并调用B*A调用A*B,但我最终会问自己:我在哪个文件中实现了A和B之间的操作,是在A还是在B中?(大约有6节课,所以我会问很多这个问题。15对可能的操作)
将来有人在执行新操作时可能会无限循环a*B调用B*a调用a*B。
有一个惯例来决定哪一个应该实施是a*B还是B*a是不自然的。
我可以创建一个第三个文件,其中包含由a*B和B*a调用的所有已实现函数,这些函数似乎不太面向对象。
您将如何解决此问题?
谢谢

(我可以列出一些代码,但它很长而且不容易说明这一点)

你是对的,你绝对不应该将
A*B
作为
B*A
的调用来实现。除了创建无限调用链的可能性之外,这种方法也不能反映代码中操作的对称性,因为代码是不对称的


更好的方法是在助手类中实现“对称”操作或作为顶级函数,具体取决于您的语言支持什么,然后让
A*B
B*A
调用该助手实现。

我的建议是使用将充当参数生成器的生成器

new ParameterBuilder()
    .setFirst( "A" )
    .setSecond( "B" )
    .setThird( "C" )
    ...
    .build();

然后您将只有一个方法将
ParameterBuilder
作为参数。

有一条指导原则,类使用其他类的属性并不完全合适。我猜Meyer的这本书没有什么好的,他在他的更有效的C++书中有一个很好的讨论(项目31:使函数相对于多个对象是虚拟的)。他的例子是为一个游戏中的各种物体可能在空间碰撞的碰撞函数。他的例子也是对称的(无论小行星撞上宇宙飞船还是宇宙飞船撞上小行星,爆炸都是一样的)。他从访问者的模式开始,逐步设计出一种依赖于RTTI的C++特定解决方案。@ TITUS非常确信它是(我在1997阅读了这本书,而该项目就在那里)。我尝试用RTTI实现,我使用Type ID()(NAME()),它非常慢,然后我尝试为每个返回INT的子类做静态函数,这是函数指针矩阵中的索引之一。它仍然比访客模式慢3倍。这是一个非常奇怪的存储库@titus。你的函数真的很快吗,所以分派机制的改变会导致3倍的速度减慢?嗯,我可以实现如下内容:
Object*result=new MultiplyHelper().addOperator(“a”).addOperator(“B”).compute()我也有一些非交换函数,比如A/B,在非对称操作中使用上述对称结构是不合适的。另一种方法更好。参数生成器只用于获取参数。如何处理这些参数取决于您自己。你所做的也很好。我建议此解决方案保持方法的完整性,只更改方法签名。