我正在研究串行数据协议的解析器。我有一个总体Packet
类,一些子类,如CommandPacket
和StatusPacket
,然后是每个子类的几个子类:
Packet
类有一个静态方法用于从缓冲区中获取数据,如果它表示有效数据包,则返回Packet
类的新实例,并使用必要的数据进行实例化。 / p>
现在,这就是我出现问题的地方。我希望能够返回最具体的类型的数据包。为了实现这一点,我创建了一个静态.isValid()
方法,该方法在子类上被重写。我的想法是,我可以遍历每种类型的特定数据包(CommandTypeA
,CommandTypeB
,StatusTypeA
,StatusTypeB
等),并调用.isValid()
,直到其中一个他们返回TRUE
。此时,我将返回该特定数据包类型的新实例。
当然,我可以直接创建此方法,如何解决未添加到项目中的数据包类型?我希望将来有人能够扩展我的课程,而无需修改原来的Packet
课程。
我考虑过利用反射,但我避免使用它,因为这些方法会被收到的每个数据包调用,并且必须有效。
有关如何重新设计我的设计模式的想法吗?
虽然我认为它不完全与讨论相关,但我在VB.NET中这样做。此处发布的问题类似(但不完全相同):Java - subclass validation design pattern
答案 0 :(得分:2)
基于评论和MarkJ的主角,这是一个建议(最终基于接口而不是强类型检查的属性):
public interface IPacketValidator
{
bool IsPacketValid( Packet packet );
Type PacketType { get; }
}
public class ValidatorsRegistry
{
private List<IPacketValidator> m_validatorsList;
private static ValidatorsRegistry m_Instance = new ValidatorsRegistry();
public static ValidatorsRegistry Instance { get { return m_Instance; } }
private ValidatorsRegistry()
{
InitValidatorsRegistry();
}
private void InitValidatorsRegistry()
{
m_validatorsList = new List<IPacketValidator>();
Type iPacketValidatorType = typeof( IPacketValidator );
foreach ( Assembly asm in AppDomain.CurrentDomain.GetAssemblies() )
{
foreach ( Type type in asm.GetTypes() )
{
if ( iPacketValidatorType.IsAssignableFrom( type ) && type != iPacketValidatorType )
{
IPacketValidator validator = (IPacketValidator)Activator.CreateInstance(type);
m_validatorsList.Add( validator );
}
}
}
}
public Type GetSpecificPacketType(Packet packet)
{
Type packetType = typeof( Packet );
foreach ( IPacketValidator validator in m_validatorsList )
{
if ( validator.IsPacketValid( packet ) )
{
packetType = validator.PacketType;
break;
}
}
return packetType;
}
}
答案 1 :(得分:1)
对于依赖注入容器或MEF,这是一个完美的用例。
但是回到这个问题,所以你需要同时具有Packet
状态和能够在不设置此状态的情况下进行验证。这里有几种选择,既不完美:
PacketFactory
并允许多个工厂(用于可扩展性)。缺点:如果选择逻辑与数据包类型紧密耦合,它会创建两个真实来源。Func<X, Packet>
列表,如果Packet
有效,Func将返回X
个实例,如果不是null
则返回{{1}} 。缺点:没有静态保证实现此方法。在所有这些情况下,可以使用自定义案例中的启动反射或使用所选DI框架提供的任何扩展机制来完成发现。