C#泛型: 消除Visitor模式的循环依赖, 以及无聊的Accept方法

本文探讨了经典访客模式中的循环依赖问题,并提出两种改进方案:一是通过DownCast方式解耦;二是利用C#泛型特性消除重复的Accept方法,使代码更简洁高效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几天跟Yuan Ye Pair的时候发现了这个方法

1. 经典的Visitor模式(循环依赖)

public interface Document { void Accept(DocumentVisitor visitor); } public class WordDocument : Document { public void Accept(DocumentVisitor visitor) { visitor.Visit(this); } } public class ExcelDocument : Document { public void Accept(DocumentVisitor visitor) { visitor.Visit(this); } } public interface DocumentVisitor { void Visit(WordDocument wordDocument); void Visit(ExcelDocument excelDocument); }

这里面 Document依赖于DocumentVisitor, DocumentVisitor依赖于WordDocument和ExcelDocument, 而WrodDocument等又依赖于Document

这样 Document->DocumentVisitor->WordDocument->Document->...循环依赖
2. 经典的解依赖Visitor模式(Down Cast)
public interface Document { void Accept(DocumentVisitor visitor); } public class WordDocument : Document { public void Accept(DocumentVisitor visitor) { if (visitor is WordDocumentVisitor) { ((WordDocumentVisitor)visitor).Visit(this); } } } public class ExcelDocument : Document { public void Accept(DocumentVisitor visitor) { if (visitor is ExcelDocumentVisitor) { ((ExcelDocumentVisitor)visitor).Visit(this); } } } public interface DocumentVisitor { //空接口, 依赖在这里断掉了 } public class ExcelDocumentVisitor : DocumentVisitor { public void Visit(ExcelDocument excelDocument) { } } public class WordDocumentVisitor : DocumentVisitor { public void Visit(WordDocument wordDocument) { } }

3. 消除无聊Accept()方法的Visitor模式

上面的Accept方法几乎千篇一律, 遵循相同的模式. 里面无非就是类型计算, 可以利用C#的泛型支持将之消除
public interface Document { void Accept(DocumentVisitor visitor); } public abstract class VisitableDocument<T> : Document where T : VisitableDocument<T> { public void Accept(DocumentVisitor visitor) { var interfaces = visitor.GetType().GetInterfaces(); foreach (var type in interfaces) { if (type.GetGenericArguments().Contains(typeof(T))) { ((DocumentVisitor<T>)visitor).Visit((T)this); } } } } public class WordDocument : VisitableDocument<WordDocument> { //不需要自己实现Accept, 基类已经实现 } public class ExcelDocument : VisitableDocument<ExcelDocument> { //不需要自己实现Accept, 基类已经实现 } public interface DocumentVisitor { //空接口 } public interface DocumentVisitor<T> : DocumentVisitor where T : VisitableDocument<T> { //泛型, 依赖在这里断掉了 void Visit(T document); } public class PrintDocumentVisitor : DocumentVisitor<WordDocument>, DocumentVisitor<ExcelDocument> { public void Visit(WordDocument wordDocument) { } public void Visit(ExcelDocument excelDocument) { } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值