如何解决如何创建工厂以创建接受更多派生类型参数的派生对象
我在为基于公共的类系列的工厂设计合适的解决方案时遇到了问题。我有一个名为 Verifier 的类,该类将只有方法 Verify ,它接受 Specification 的实例作为参数
public abstract class Verifier
{
public virtual bool Verify(Specification spec)
{
//does the common job
return true; //or false
}
}
然后我有一组具体的验证器
public abstract class FirstVerifier : Verifier
{
public override bool Verify(Specification spec)
{
//does the job,maybe even calls for base or maybe not
return true;
}
}
public abstract class SecondVerifier : Verifier
{
public override bool Verify(Specification spec)
{
//does the job,maybe even calls for base or maybe not
return true;
}
}
public class VerifierFactory
{
public static Verifier Create(string type) //not actually a string,but does not matter
{
switch (type)
{
case "First": return new FirstVerifier();
case "Second": return new SecondVerifier();
default: throw new Exception();
}
}
}
现在我有一个要求,即验证者可以验证的不是规范的实例,而是规范的派生类型,例如:
public abstract class FirstVerifier : Verifier
{
public override bool Verify(SpecificationOne spec) //SpecificationOne derives from Specification
{
//does the job,maybe even calls for base or maybe not
return true;
}
}
public abstract class SecondVerifier : Verifier
{
public override bool Verify(SpecificationTwo spec) //SpecificationOne derives from Specification
{
//does the job,maybe even calls for base or maybe not
return true;
}
}
这显然不会编译,我不想做这样的伎俩:
public abstract class FirstVerifier : Verifier
{
public override bool Verify(Specification spec)
{
var realSpecification = spec as SpecificationOne;
if(realSpecification == null)
throw new Exception();
// do job
}
}
我正在考虑一种解决方案(可能是通用的),其中我的工厂返回正确的类型,然后在验证方法中接受正确的类型,这样我就可以使用我的工厂创建验证程序并调用验证,如下所示:
specifications.Select(s => VerifierFactory.Create(typeof(s)).Verify(s))
解决方法
我认为您可以使用泛型方法。例如:
public abstract class Verifier
{
public virtual bool Verify<T>(T spec) where T: Specification
{
//does the common job
return true; //or false
}
}
或者你可以使用泛型类,例如:
创建基础 Specification
类
public class Specification
{
//some properties,fields and etc
}
并从基础 Specification
类继承您的其他规范
public class SpecificationOne : Specification
{
//some properties,fields and etc
}
public class SpecificationTwo : Specification
{
//some properties
}
创建基 Verifier
类后,它是泛型类。
public abstract class Verifier<T> where T : Specification
{
public virtual bool Verify(T spec)
{
//does the common job
return true; //or false
}
}
并从基 Verifier<T>
类继承其他验证器类。 这些类必须不是抽象的,因为我们将在 VerifierFactory
中创建实例。例如:
public class FirstVerifier : Verifier<SpecificationOne>
{
public override bool Verify(SpecificationOne spec)
{
var baseResult = base.Verify(spec);
//some logic
return baseResult;
}
}
public class SecondVerifier : Verifier<SpecificationTwo>
{
public override bool Verify(SpecificationTwo spec)
{
var baseResult = base.Verify(spec);
//some logic
return baseResult;
}
}
您可以像下面这样创建 VerifierFactory
:
public class VerifierFactory
{
public static Verifier<T> Create<T>(T spec) where T : Specification
{
if (spec.GetType() == typeof(SpecificationOne))
return new FirstVerifier() as Verifier<T>;
if (spec.GetType() == typeof(SpecificationTwo))
return new SecondVerifier() as Verifier<T>;
//and etc...
// I think you project must have one default Verifier class for else case
}
}
最后,您可以使用如下所示的 linq 查询:
specifications.Select(s => VerifierFactory.Create(s).Verify(s))
,
考虑这个解决方案。从通用的基本验证器开始,并提供验证 Specification
部分的默认实现,然后调用子类的实现来验证 T
部分。
public abstract class Verifier<T> where T : Specification
{
// in most cases you probably wouldn't override this
// in subclasses,but you could if necessary
public virtual bool Verify(Specification spec)
{
if (!VerifyCommon(spec)) return false;
return VerifyImplementation((T)spec);
}
protected abstract bool VerifyImplementation(T spec);
protected bool VerifyCommon(Specification spec)
{
//does the common job
return true; //or false
}
}
你的工厂根本不需要改变。您的子类将在每种情况下实现抽象 VerfifyImplementation
。
public class FirstVerifier : Verifier<SpecificationOne>
{
protected override bool VerifyImplementation(SpecificationOne spec)
{
// do job
return ...;
}
}
您的 select
必须更改为类似的内容
specifications.Select(s => VerifierFactory.Create(s.GetType()).Verify(s))
此解决方案的优点是在每种情况下应用相同的验证模式,并避免在子类中进行强制转换(尽管您确实在基类中进行了强制转换)。
然而,此解决方案有一个缺点,即 FirstVerifier
可能接受 Specification
中 Verify(Specification)
的错误子类。要解决此问题,您可以将基本验证器更改为
public abstract class Verifier<T> where T : Specification
{
public virtual bool Verify(T spec)
{
if (!VerifyCommon(spec)) return false;
return VerifyImplementation(spec);
}
protected abstract bool VerifyImplementation(T spec);
protected bool VerifyCommon(Specification spec)
{
//does the common job
return true; //or false
}
}
但这意味着您的 select
将不得不执行一些动态魔法以确保可以正确调用 Verify
方法:
specifications.Select(s => VerifierFactory.Create(s.GetType()).Verify((dynamic)s))
此实现消除了 Verify
内部的强制转换并确保了类型安全,但动态调用 Verify
方法的成本(可能可以忽略不计)。
这两种实现的好处是它们
- 避免调用
base.Verify()
,当子类的开发人员忘记调用base.Verify()
时,这有时会导致错误。 - 可以对
Specification
的异构列表进行操作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。