我正在寻找一种方法来实现可以为方法和类扩展的双重调度。
到目前为止,我基本上使用了三种方法:
- 传统的程序方法非常好
switch
(容易添加新功能,很难添加新类) - 访问者模式(非常相似:容易添加新访问者,很难添加新类)
- 一个简单的接口方法(容易添加新类,很难添加新功能)
我正在寻找一种无需修改函数或现有类即可添加新函数和新类的方法。
在请求对象/函数的某种组合时,这不应该失败,至少在程序启动后我可以做一次检查之后不会失败。
以下是我目前使用的方法:
传统的程序方法:
enum WidgetType {A,B,C,}
interface IWidget
{
WidgetType GetWidgetType();
}
class WidgetA
{
public WidgetType GetWidgetType() {return WidgetType.A;}
}
class WidgetB
{
public WidgetType GetWidgetType() {return WidgetType.B;}
}
class WidgetC
{
public WidgetType GetWidgetType() {return WidgetType.C;}
}
// new classes have to reuse existing "WidgetType"s
class WidgetC2
{
public WidgetType GetWidgetType() {return WidgetType.C;}
}
class Functions
{
void func1(IWidget widget)
{
switch (widget.GetWidgetType())
{
case WidgetType.A:
...
break;
case WidgetType.A:
...
break;
case WidgetType.A:
...
break;
default:
// hard to add new WidgetTypes (each function has to be augmented)
throw new NotImplementedException();
}
}
// other functions may be added easily
}
传统的面向对象方法(Visitor-Pattern):
interface IWidgetVisitor
{
void visit(WidgetA widget);
void visit(WidgetB widget);
void visit(WidgetC widget);
// new widgets can be easily added here
// but all visitors have to be adjusted
}
interface IVisitedWidget
{
void accept(IWidgetVisitor widgetVisitor);
}
class WidgetA : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetA(){}
}
class WidgetB : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetB(){}
}
class WidgetC : IVisitedWidget
{
public void accept(IWidgetVisitor widgetVisitor){widgetVisitor.visit(this);}
public void doStuffWithWidgetB(){}
}
class SampleWidgetVisitor : IWidgetVisitor
{
public void visit(WidgetA widget){ widget.doStuffWithWidgetA(); }
public void visit(WidgetB widget){ widget.doStuffWithWidgetB(); }
public void visit(WidgetC widget){ widget.doStuffWithWidgetC(); }
}
简单的界面方法:
IWidget
{
void DoThis();
void DoThat();
// if we want to add
// void DoOtherStuff();
// we have to change each class
}
WidgetA : IWidget
{
public void DoThis(){ doThisForWidgetA();}
public void DoThat(){ doThatForWidgetA();}
}
WidgetB : IWidget
{
public void DoThis(){ doThisForWidgetB();}
public void DoThat(){ doThatForWidgetB();}
}
WidgetC : IWidget
{
public void DoThis(){ doThisForWidgetC();}
public void DoThat(){ doThatForWidgetC();}
}