我正在尝试为更简单的语言编写一个简单的编译器,但是我在添加Visitor
模式时遇到了问题。
我有一个ILanguageVisitor
界面,如下所示:
interface ILanguageVisitor {
void Visit(GlobalStructure cs);
void Visit(GotoStructure cs);
void Visit(IfStructure cs);
void Visit(ElseIfStructure cs);
void Visit(ElseStructure cs);
...
}
必须实现所有这些方法以创建特定体系结构的具体访问者。但除此之外,还有一些方法和领域应该适用于所有可能的访问者。
这就是块的功能,它包含两个或更多Visit
个调用,如:
Visit(If)
...
Visit(Else)
...
Visit(EndIf)
Visit(For)
...
Visit(EndFor)
这是因为块启动和终止的规则(就像一个块中不能有两个else
,或者父块不能终止子块{{1} })。
我的问题是:如果我的行为对于所有For ... If ... EndFor
都应该是通用的,那么我应该创建一个抽象的Visitor类,它会使这些特定的方法Visitor
和其他{{1} }?
如果我向其基础添加默认行为,是否会丢失virtual
点?
答案 0 :(得分:2)
在这种情况下,我认为最好的解决方案是同时拥有一个实现此接口的接口和基类,并允许用户覆盖某些方法。这样,用户可以决定他是否愿意:
答案 1 :(得分:2)
至于我,访客模式是一个聪明的If-Else结构,看看这个解决方案
public static class Visitor
{
public static IFuncVisitor<TBase, TResult> For<TBase, TResult>()
where TBase : class
{
return new FuncVisitor<TBase, TResult>();
}
public static IActionVisitor<TBase> For<TBase>()
where TBase : class
{
return new ActionVisitor<TBase>();
}
private sealed class ActionVisitor<TBase> : IActionVisitor<TBase>
where TBase : class
{
private readonly Dictionary<Type, Action<TBase>> _repository =
new Dictionary<Type, Action<TBase>>();
public void Register<T>(Action<T> action)
where T : TBase
{
_repository[typeof(T)] = x => action((T)x);
}
public void Visit<T>(T value)
where T : TBase
{
Action<TBase> action = _repository[value.GetType()];
action(value);
}
}
private sealed class FuncVisitor<TBase, TResult> : IFuncVisitor<TBase, TResult>
where TBase : class
{
private readonly Dictionary<Type, Func<TBase, TResult>> _repository =
new Dictionary<Type, Func<TBase, TResult>>();
public void Register<T>(Func<T, TResult> action)
where T : TBase
{
_repository[typeof(T)] = x => action((T)x);
}
public TResult Visit<T>(T value)
where T : TBase
{
Func<TBase, TResult> action = _repository[value.GetType()];
return action(value);
}
}
}
public interface IFuncVisitor<in TBase, TResult>
where TBase : class
{
void Register<T>(Func<T, TResult> action)
where T : TBase;
TResult Visit<T>(T value)
where T : TBase;
}
public interface IActionVisitor<in TBase>
where TBase : class
{
void Register<T>(Action<T> action)
where T : TBase;
void Visit<T>(T value)
where T : TBase;
}
用法示例:
IActionVisitor<Letter> visitor = Visitor.For<Letter>();
visitor.Register<A>(x => Console.WriteLine(x.GetType().Name));
visitor.Register<B>(x => Console.WriteLine(x.GetType().Name));
Letter a = new A();
Letter b = new B();
visitor.Visit(a);
visitor.Visit(b);
其中Letter
是A
和B
答案 2 :(得分:1)
设计模式是设计问题的解决方案,而不是实施规则。因此,如果您选择使用接口,抽象类或两者(如@AdiLester建议)实现访问者模式完全由您决定
如果我没记错的话,原来的GOF书中使用了很多C ++的例子,其中甚至没有语言元素接口。