假设你有这样的代码:
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不需要这个参数,代码就会变得很难闻。重写这段代码的方法有哪些?
发布于 2011-10-17 19:31:29
您可以在这里使用对象作为参数;这通常用于参数数量随所使用的调用而变化的场景。
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)
{
}
}
发布于 2011-10-17 18:55:57
在Registrator3中不能包含externalParam的逻辑吗?换句话说,Registrator3使用参数,然后调用未修改的无参数base?
这在很大程度上取决于逻辑的归属。如果它是基类的固有属性,则将其放在基类中,然后重载Register()函数或为参数提供默认值,这样子类就不需要提供它。
发布于 2011-10-17 19:15:39
假设您想要重用基类中的注册逻辑,您可以按如下方式更新代码:
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,
Cosmin
编辑:更新要编译的代码。
https://stackoverflow.com/questions/7792567
复制相似问题