(嵌套?)多重调度 [访客模式]
我的应用程序架构遇到了障碍。我刚刚开始使用访问者模式对我在运行时不知道的类型的抽象对象执行特定的算法。 我的问题是我的算法也取决于嵌套抽象类型的类型。
让我说明我的意思:
我有一个抽象 DataSource 类。由此我实现了具体的 DataSourceReference 和 DataSourceExplicit 类。我还有一个抽象的 Report 类(反序列化的元数据),从中我实现了具体的 Report 类 ReportTypeA 和 ReportTypeB。创建这些对象时,它们的 DataSource 可以是任何扩展 DataSource 类。
我需要两者,即实际的报表类型和数据源类型,以便我可以相应地执行。我可以使用访问者模式获取一致的报告类型,但不知道如何对数据源之后/也执行相同的操作。
访问报表后我无法访问数据源,因为我会丢失报表的具体类型(因为您必须让它接受基本报表类型:Accept(SomeDataSourceVisitor d, MetaReport m) - 或每种可能的报表类型的重载,这违背了访问者模式的目的。看到我的问题了
吗?我想远离使用动态,因为它不需要新报告类型的开发人员来确保调度程序(访问者)支持新报告。 。
当前的 代码:
public abstract class DataSource
{
}
public class DataSourceReference : DataSource
{
// reference thing(s)
}
public class DataSourceExplicit : DataSource
{
// explicit thing(s)
}
public abstract class Report
{
// some shared Report attribute(s)
// ...
public DataSource DataSource { get; set; }
public abstract FinalReport Execute(IReportExecutionDispatcher d);
}
public class ReportA : Report
{
// ReportA specific attribute(s)
// ...
public override Execute(IReportExecutionDispatcher d)
{
d.ExecuteReport(this);
}
}
public class ReportB : Report
{
// ReportB specific attribute(s)
// ...
public override Execute(IReportExecutionDispatcher d)
{
d.ExecuteReport(this);
}
}
public interface IReportExecutionDispatcher
{
FinalReport ExecuteReport(ReportA);
FinalReport ExecuteReport(ReportB);
}
I've come to a road block in my application architecture. I've just started using the visitor pattern to execute specific algos on abstract objects of which type I don't know at runtime. My problem is that my algo also depends on the type of a nested abstract type as well.
Let me illustrate what I mean:
I have an abstract DataSource class. From this I implement concerete DataSourceReference and DataSourceExplicit classes. I also have an abstract Report class (the deserialized metadata), from which I implement concrete Report classes ReportTypeA and ReportTypeB. When these objects are created, their DataSource may be any extending DataSource class.
I need both, the actual Report type and DataSource type so I can execute accordingly. I can get the concerte Report type using the visitor pattern, but don't know how to do the same for DataSource afterwards/also.
I can't visit DataSource after visiting Report, because I'd lose the concrete type of Report (as you would have to let it accept the base Report type: Accept(SomeDataSourceVisitor d, MetaReport m) - or overload for every possible Report type, which defeats the purpose of Visitor Pattern. See my problem?
Any ideas? I'd like to stay away from using dynamic, as it wouldn't require developers of new Report types to make sure the dispatcher(visitor) supports the new Report.
Current Code:
public abstract class DataSource
{
}
public class DataSourceReference : DataSource
{
// reference thing(s)
}
public class DataSourceExplicit : DataSource
{
// explicit thing(s)
}
public abstract class Report
{
// some shared Report attribute(s)
// ...
public DataSource DataSource { get; set; }
public abstract FinalReport Execute(IReportExecutionDispatcher d);
}
public class ReportA : Report
{
// ReportA specific attribute(s)
// ...
public override Execute(IReportExecutionDispatcher d)
{
d.ExecuteReport(this);
}
}
public class ReportB : Report
{
// ReportB specific attribute(s)
// ...
public override Execute(IReportExecutionDispatcher d)
{
d.ExecuteReport(this);
}
}
public interface IReportExecutionDispatcher
{
FinalReport ExecuteReport(ReportA);
FinalReport ExecuteReport(ReportB);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在网上搜索的时候也发现了这个。发布在这里以供将来参考和讨论。
选择性访客模式
Also found this while scouring the interwebs. Posting it here for future reference and discussion.
Selective Visitor Pattern
您想要有 N * M 方法,其中 N 是报表类型的计数,M 是数据源类型的计数。我认为这里正确的方法是将它们分成 N 种类型,每种类型都有 M 种方法,再加上一个辅助类型,这有助于我们迈出调度的第一步。像这样:
现在我们只需要修改我们的数据源以接受新的调度程序:
并修改报告:
You want to have N * M methods, where N is the count of report types and M is the count of data source type. I think the right approach here is to split them into N types, each with M methods, plus one helper type, that helps us make the first step in dispatching. Something like this:
Now we just need to modify our data sources to accept the new dispatcher:
And also modify reports: