我正在使用Divan CouchDB库的一个分支,并且需要在幕后使用的httpwebrequest上设置一些配置参数。起初我开始通过构造函数的所有层和涉及的方法调用来线程化参数,但随后决定 - 为什么不传入配置委托?
所以在更通用的场景中,
给出:
class Foo {
private parm1, parm2, ... , parmN
public Foo(parm1, parm2, ... , parmN) {
this.parm1 = parm1;
this.parm2 = parm2;
...
this.parmN = parmN;
}
public Bar DoWork() {
var r = new externallyKnownResource();
r.parm1 = parm1;
r.parm2 = parm2;
...
r.parmN = parmN;
r.doStuff();
}
}
做的:
class Foo {
private Action<externallyKnownResource> configurator;
public Foo(Action<externallyKnownResource> configurator) {
this.configurator = configurator;
}
public Bar DoWork() {
var r = new externallyKnownResource();
configurator(r);
r.doStuff();
}
}
后者对我来说似乎更加清晰,但它确实向外界揭示class Foo
使用externallyKnownResource
想法?
答案 0 :(得分:2)
这可以带来更清晰的外观代码,但却有一个巨大的劣势。
如果您使用委托进行配置,则会失去对对象配置方式的大量控制。问题是代表可以做任何事情 - 你无法控制这里发生的事情。你让第三方在你的构造函数中运行任意代码,并相信他们做“正确的事情”。这通常意味着您最终必须编写大量代码以确保委托正确设置所有内容,或者您可以使用非常脆弱,易于破解的类。
验证委托是否正确设置了每个要求变得更加困难,特别是当您深入到树中时。通常,验证代码最终会比原始代码更加混乱,通过层次结构传递参数。
答案 1 :(得分:1)
我可能在这里遗漏了一些东西,但在DoWork()中创建externalKnownResource对象似乎是一个很大的缺点。这排除了替代实施的简单替代。 为什么不:
public Bar DoWork( IExternallyKnownResource r ) { ... }
答案 2 :(得分:0)
IMO,你最好接受一个配置对象作为你的Foo构造函数的一个参数,而不是十几个(左右)单独的参数。
修改:
没有一个适合所有人的解决方案,没有。但问题很简单。我正在写一些消耗外部已知实体(httpwebrequest)的东西,它已经自我验证并且有大量可能必要的参数。实际上,我的选择是重新创建它所具有的几乎所有配置参数,并且每次都将它们移动,或者将消费者放在消费者手中以便按照自己的意愿进行配置。 - kolosy
您的请求的问题在于,一般来说,如果类的用户配置外部资源(即使它是众所周知的或常用的资源),那么类设计很差。让你的班级从你班级的用户那里隐藏所有这些是更好的班级设计。这意味着你的课程中有更多的工作,是的,将配置信息传递给你的外部资源,但这就是拥有一个单独的类的重点。否则,为什么不让你班级的来电者在你的外部资源上做所有的工作呢?为什么首先要单独上课呢?
现在,如果这是一个内部类,为你将永远控制的另一个类做一些简单的实用工作,那么你就没事了。但不要公开披露这种类型的范例。