假设你有这样的代码:
public Base
{
abstract void Register();
}
public Registrator1: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
public Registrator2: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
但是当你收到一个新的业务规则,要求你编写Registrator3,它实际上是根据某个参数注册的,你将代码库更改为下一个:
public Base
{
abstract void Register(externalParam);
}
public Registrator1: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate theUI
}
}
public Registrator2: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate the UI
}
}
public Registrator3: Base
{
override void Register(externalParam)
{
//uses a DDD - service passed in the params to populate the UI
}
}
但Registrator1和Registrator2不需要那个参数,代码变得很臭。有什么方法可以重写这段代码?
答案 0 :(得分:2)
您可以在此处使用对象作为参数;这种情况通常用于参数数量因使用的呼叫而异的情况。
struct RegistrationInfo
{
public static readonly RegistrationInfo Empty = new RegistrationInfo();
public string Username;
public string CustomerName;
public string Validity;
}
abstract class Base
{
public abstract void Register(RegistrationInfo info);
// If you want to retain the paramaterless call:
public void Register()
{
Register(RegistrationInfo.Empty);
}
}
class Registrar1 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.Username == null) throw new ArgumentNullException("info.Username");
}
}
class Registrar2 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.CustomerName == null) throw new ArgumentNullException("info.CustomerName");
}
}
这样做的好处是,每次添加参数时都不需要更改方法参数(即破坏界面)。用法也变得有些自我记录:
var r = new Registrar1();
r.Register(new RegistrationInfo(){ Username = "JimJoe" });
r.Register(RegistrationInfo.Empty);
对于这种类型的代码气味,它就像空气清新剂,而它仍然很臭;你可以让它闻起来更好。
最后,您可以通过使其成为params
参数来使呼叫站点更清洁(这会产生少量开销);说实话虽然它更臭,但因为它是一种语言黑客。最后,您可以使用泛型来改进它:
class RegistrationInfo
{
}
class RegistrationInfo1 : RegistrationInfo
{
public string Arg;
}
class RegistrationInfo2 : RegistrationInfo
{
public int Arg;
}
interface IBase<in TRegistration>
where TRegistration : RegistrationInfo
{
void Register(TRegistration registration);
}
class Base : IBase<RegistrationInfo>
{
public void Register(RegistrationInfo registration)
{
}
}
class Registrar1 : IBase<RegistrationInfo1>
{
public void Register(RegistrationInfo1 arg)
{
}
}
class Registrar2 : IBase<RegistrationInfo2>
{
public void Register(RegistrationInfo2 arg)
{
}
}
答案 1 :(得分:0)
在Registrator3中是否无法包含externalParam的逻辑? 换句话说,Registrator3使用param,然后调用未修改的无参数基础?
很大程度上取决于逻辑所属的位置。如果它是base的内在属性,那么将它放在base中,并重载Register()函数或为param提供一个默认值,以便子类不需要提供它。
答案 2 :(得分:0)
假设您要重用基类中的注册逻辑,可以按如下方式更新代码:
public class Base
{
public virtual void Register(object externalParam)
{
// base registration logic goes here
}
}
public class Registrator1: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator2: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator3: Base
{
public override void Register(object externalParam)
{
base.Register(externalParam);
// custom registration logic goes here
}
}
HTH,
科斯明
编辑:更新了要编译的代码。