我有一个Configurator
类,为了完成它的工作,必须通过一个接口接收一个Context
对象:
public class Configurator : IContextAware
{
private IContext _context;
//property setter defined by the IContextAware interface
public IContext Context { set { _context = value; } }
// use _context object in other methods here ...
}
我计划编写多种Configurator
类型,这些类型都需要以同样的方式初始化_context
字段。我的第一个想法是“为什么不激怒互联网上的每个程序员并使用继承”?
public class ContextInitializer: IContextAware
{
// field to hold the injected context
protected IContext _context;
//property setter defined by the IContextAware interface
public IContext Context { set { _context = value; } }
}
public class Configurator : ContextInitializer
{
// use _context object here ...
}
这样,我编写的任何需要Context对象的其他类只能从ContextInitializer继承,并立即使用Context对象。
优点:保证一致的初始化,不会分散注意力,在每个类中重复初始化代码
缺点:实现继承是邪恶的!,..嗯,Configurator不能从任何其他类继承.. ??
我应该澄清一下,Configurator必须实现IContextAware
接口。此外,该类必须具有default / no-arg构造函数,因此构造函数依赖注入不是一个选项。
有人可以建议如何使用Composition来实现相同的好处,但设计更灵活,和/或描述上面的继承解决方案的真正缺点?谢谢!
P.S。这是改编自Spring.Net CodeConfig,如果有人好奇的话。
答案 0 :(得分:1)
我认为.NET基类库是一个很好的标准来回答这些问题。您对继承的使用从未被放入BCL ,因为它会将您的API用户暴露给API内部。现在有一个没有任何语义含义的基类。它只存在以保存代码。所有公共API元素都应具有目的和语义含义。
对于API设计,BCL的作者显然非常严格。我从来没有见过如此庞大但原始的原型。
也就是说,如果您不需要那种级别的API清洁度,则不需要遵循相同的标准。 并非每个API都会暴露给数百万开发人员。为了节省大量代码并消除冗余和潜力,对API纯度进行妥协是合法的权衡错误。
我的选择:我会将您的方法用于内部代码。对于公共API(想想Codeplex库等),我宁愿复制冗余内容并保持公共API表面清洁。