问题
我发誓,每次我把它敲进我的大脑时,我都应该使用虚拟呼叫与类型检查(例如:
if (obj is Foo)
...
else if (obj is Bar)
...
...我想出了另一个例子,我不知道如何实现前者。
我正在通过串行端口实现分组协议。一些伪代码将最好地解释这一点:
OnDataReceived:
RcvPacket p = RcvPacket.ReadPacket(comport); // Call factory method
if (p is RcvPacketFoo)
OnFoo();
if (p is RcvPacketBar)
OnBar();
OnFoo:
raise Foo event
OnBar:
raise Bar event
基本上,ReadPacket 是基类中的一个工厂方法,它确定接收到的数据包的类型,并将缓冲区传递给正确的派生类型构造函数。在此之后,我需要根据数据包的类型引发一个事件。在不使用操作员的情况下如何做到这一点?我的方法健全/健全吗?is
解决方案
在这种情况下,我使控制器,即调用工厂方法,是访问者。我的结果:
public interface IPacketHandler {
void Handle(FooPacket p);
void Handle(BarPacket p);
}
public class Controller : IPacketHandler {
OnDataReceived() {
RcvPacket p = RcvPacket.ReadPacket(comport); // Call factory method
p.Handle(this); // *** Virtual Call: The first dispatch ***
}
// Note the use of explicit interface implementation here.
IPacketHandler.Handle(FooPacket p) {
OnFoo();
}
IPacketHandler.Handle(BarPacket p) {
OnBar();
}
}
public abstract class RcvPacket {
public static RcvPacket ReadPacket(...) { ... } // Factory method
public void Handle(IPacketHandler handler);
}
public class FooPacket : RcvPacket {
public override void Handle(IPacketHandler handler) {
handler.Handle(this); // *** Overloaded call: The second dispatch ***
}
}
public class BarPacket : RcvPacket {
public override void Handle(IPacketHandler handler) {
handler.Handle(this); // *** Overloaded call: The second dispatch ***
}
}
有趣的是,通过显式实现访问者界面,Handle
调用本质上是隐藏的。来自MSDN:
实现接口的类可以显式地实现该接口的成员。当显式实现成员时,不能通过类实例访问它,而只能通过接口的实例访问。