我正在使用六边形架构,我想知道访客模式将如何尊重它?
访问的对象是域对象,但访问者旨在将所述域对象实现动态调度到域对象和数据传输对象之间的适当映射器。
我的第一个想法是将访问者的抽象暴露到域中,并将其实际实现保留在基础结构中,类似于存储库。
这不是揭示了域的基础设施吗?访客模式是实现细节,对吧?它不会带来任何商业价值,所以它不属于域,不是吗?但是,我需要在我的业务对象中使用 accept 方法来实现此模式。
你对此有何看法?
编辑代码示例(C# 语法,但没有什么花哨的):
namespace Domain
{
public interface IFlow
{
void Accept(IFlowVisitor visitor);
}
public class Cashflow : IFlow
{
void Accept(IFlowVisitor visitor)
{
visitor.Visit(this);
}
// some properties
}
public class Assetflow : IFlow
{
void Accept(IFlowVisitor visitor)
{
visitor.Visit(this);
}
// some properties
}
public interface IFlowVisitor
{
void Visit(Assetflow flow);
void Visit(Cashflow flow);
}
}
namespace Infra
{
public class FlowVisitor : IFlowVisitor
{
public FlowVisitor(ICashflowMapper cashflowMapper, IAssetflowMapper assetflowMapper, IDao dao)
{
CashflowMapper = cashflowMapper;
AssetflowMapper = assetflowMapper;
Dao = dao;
}
private readonly ICashflowMapper CashflowMapper {get; set;}
private readonly IAssetflowMapper AssetflowMapper {get; set;}
private readonly IDao Dao {get; set;}
public void Visit(Assetflow flow)
{
Assetflow assetflowDto = AssetflowMapper.Map(flow);
dao.Persist(assetflowDto);
}
public void Visit(Cashflow flow)
{
CashflowDto cashflowDto = CashflowMapper.Map(flow);
dao.Persist(cashflowDto);
}
}
public interface ICashflowMapper
{
CashflowDto Map(Cashflow domainObject);
}
public interface IAssetflowMapper
{
AssetflowDto Map(Assetflow domainObject);
}
public interface IDao
{
void Persist(CashflowDto dto);
void Persist(AssetflowDto dto);
}
public class cashflowDto
{
// property bag
}
public class assetflowDto
{
// property bag
}
public class Test
{
public void TestMethod()
{
ICashflowMapper cashflowMapper = new CashflowMapper();
IAssetflowMapper assetflowMapper = new AssetflowMapper();
IDao dao = new Dao();
IFlowVisitor visitor = new FlowVisitor(cashflowMapper, assetflowMapper, dao)
List<IFlow> flows = new List<IFlow> { new Assetflow(), new Cashflow(), new Assetflow() };
foreach(var flow in flows)
{
flow.Accept(visitor);
}
}
}
}
确实,这种特定的访问者模式实现涉及对域的轻微污染,但务实通常比纯粹主义者更好。如果这将是您选择的语言最实用的解决方案,否则您最终会得到更复杂的技术实现,那么利大于弊,就这样吧。
幸运的是,C# 支持使用 dynamic
关键字进行动态调度,这使您不必在域对象上使用Accept
方法。
例如
public class FlowVisitor {
public void Visit(IFlow flow) {
Visit((dynamic) flow);
}
// Specific visit methods (private)...
}