- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我学习依赖注入(inject)(并获得第一次实践经验)期间,我想知道我在考虑一个具体项目时遇到的一个问题,我想在不久的将来用 DI 解决这个问题。
对于不同的分析,我想动态创建注入(inject)依赖项的对象,因为我需要任意数量的对象,这可能会因用户与我的程序的交互而有所不同。我考虑过将这个需求实现为抽象原型(prototype)模式
public interface IAnalysis
{
SomeDataType DoSomething();
IAnalysis CreateObject();
}
从 IAnalysis 派生的类将负责从 CreateObject()
返回该类的新对象。依赖类可以在不知 Prop 体类型的情况下创建新对象,而只依赖于接口(interface),因此遵循了 DI 的一个主要概念。无论如何,从 IAnalysis 派生的类必须使用 new
关键字创建新对象。我读到在使用 DI 时应避免在注入(inject)器外部使用 new
创建对象,因此我不太确定这在 DI 中是否“允许”。另一方面,这对我来说似乎是一个非常明智的解决方案,因为类只创建它们自己的新对象,这实际上不应该损害 DI 原则。
我想的概念合理吗?我可以使用其他解决方案来实现这一目标吗?我实际上考虑过抽象工厂,但这会损害我对 DI 原则的理解。
最佳答案
I read that creating objects with
new
should be avoided outside the injector when using DI […].
这只是部分正确。我会一步一步地告诉你 new
有它的位置,使用 new
可能会很好实现您的原型(prototype)模式。
让我们从显而易见的事情开始:如果我们需要一个 B
类型的实例,那么它必须由某人在某处创建。假设我们有这个:
class C
{
void Baz()
{
B b = new B(new A(…));
b.Bar();
}
}
Baz
需要 B
为了完成它的工作。如果我们想避免new B(…)
,我们能做的最好的就是将它从代码库中的这个特定位置删除:
class C
{
C(Func<B> newB) // instead of Func<B>, we could also inject a B directly
{ // (the difference being that we would no longer control
this.newB = newB; // when the B gets created)
}
Func<B> newB;
void Baz()
{
var b = newB();
b.Bar();
}
}
但是 B
被传递给 C
的构造函数仍然必须在某处创建。只是现在它在别处。
那么我们通过避免 new
获得了什么? ? C
不再需要了解如何创建 B
的内部知识.
但是Func<B> newB
怎么会(即工厂方法)本身创建一个 B
不使用new
?看来我们不能回避new
永远。
为了说明这一点,让我们继续看另一个非常相关的示例,它更接近您的问题(在 DI 上下文中实现原型(prototype)模式):抽象工厂,另一种设计模式。假设我们有一个 BFactory
其唯一职责是创建类型的实例 B
:
interface BFactory
{
B CreateB();
}
我们可以在不使用 new
的情况下实现吗? ?让我们以与上述相同的方式尝试:
class RedundantBFactory : BFactory
{
RedundantBFactory(Func<B> newB)
{
this.newB = newB;
}
Func<B> newB;
public B CreateB()
{
return newB();
}
}
这绝对没有意义!工厂存在的全部意义在于它封装了有关如何创建某种类型实例的知识。只是因为我们想避免使用 new
在我们的工厂中,我们完全外化了这些知识,使工厂作为一个整体完全多余(因为它只是将自己的主要责任转给了另一方,后者必须做同等的工作)!
我们可以得出结论,使用 new
是合理且适当的在抽象工厂和工厂方法中(例如 BFactory
甚至上面的 newB
),如果我们不希望它们完全多余:
class UsefulBFactory : BFactory
{
public UsefulAFactory(Func<A> newA)
{
this.newA = newA;
}
Func<A> newA;
public B CreateB()
{
return new B(newA());
}
}
现在您的原型(prototype)模式:原型(prototype)模式本质上是关于对象克隆的。也就是说,所有实现 IAnalysis
的类型接口(interface)必须能够创建实例的克隆(副本)。就像上面的抽象工厂示例一样,接口(interface)的唯一目的是封装某种形式的对象创建。这是它存在的首要原因,因此实现此接口(interface)的类不得将该责任委托(delegate)给外部方。同样,使用 new
是完全合理的在这种情况下:
class W : IAnalysis
{
W(X x, Y y, …)
{
this.x = x;
this.y = y;
…
}
public IAnalysis CreateObject()
{
return new W(x, y, …);
}
}
最后一点,只是为了强调和完善我最初的声明,即避免 new
并非在所有情况下都有意义:请注意,无论如何,DI 不应该用于所有。
通常,您必须决定哪些类型应该由 DI 容器处理。这些所谓的依赖项、组件或服务通常被抽象为 interface
。或 abstract class BaseClass
,这样您以后就可以用一种实现替换另一种实现。唯一使用new Service(…)
的地方应该在组合根中,或者(如上所示)在抽象工厂或工厂方法中(它们本身是依赖项,将在您选择的时间注入(inject)到您需要创建对象的位置)。如果你有 new Service(…)
大量散布在您的代码库中,很难用一种实现替换另一种实现。
但是使用 new
是完全可以的创建原始值和值类型的实例(例如 string
、 TimeSpan
等)。这些类型通常不由 DI 容器实例化。
关于c# - 原型(prototype)模式是否符合依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26250858/
以下代码,我使用 chrome 浏览器控制台进行了检查: function A(){ this.a='a' } 这是一个构造函数。我已经将一个属性 b 赋给了 A 的原型(prototype)。
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 5年前关闭。 Improve this
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 3年前关闭。 Improve this
我已经开始阅读 The Pragmatic Programmer,我很喜欢并学习堆形式,但我很难理解示踪子弹和原型(prototype)之间的区别。跟踪项目符号是否像拥有应用程序的所有 View 但尚
尽管阅读了 StackOverflow 上的大多数文章,但我现在实际上对原型(prototype)非常困惑。 function Foo() { } Foo.prototype.speak = func
我正在阅读以下代码,并开始想知道 Rectangle.prototype = Object.create(Shape.prototype) 和 Rectangle.prototype = Shape.
我想知道它们之间的区别: childObj.prototype = Object.create(parentObj.prototype) 和 childObj.prototype = parentOb
这个问题在这里已经有了答案: Why wouldn't I use Child.prototype = Parent.Prototype rather than Child.prototype =
在 node.js 中导出原型(prototype)的首选方法是什么?您可以采用两种方法: 导出原型(prototype)本身 function A () { } module.exports = A
我正在学习 JavaScript,发现了两种分配原型(prototype)的方法。 第一个是A.prototype = B.prototype,第二个是A.prototype = new B() 例如
在一些构造函数的定义之后,例如 child ,我见过以下两种形式: Child.prototype = Parent.prototype; 或 Child.prototype = new Parent
我正在阅读一本关于 OOP javascript 的书,但被其中一个示例卡住了。 在示例代码的第一个版本中,Shape 的一个新实例构造函数被创建并且 toString方法被调用。 toString方
这个问题在这里已经有了答案: What should I connect to the child prototype property in JavaScript (2 个答案) 关闭 8 年前。
在进行原型(prototype)设计时,您在多大程度上放弃了最佳实践来支持代码和修复黑客攻击?当然,代码并不打算在完整的生产环境中保留。 补充:我正在研究一个用 Python 制作的相当大的半工作原型
我正在尝试使用 Prototype 更新隐藏表单字段的值。表单域: 我正在尝试使用原型(prototype)更新值: var additionalVal = ',2'; var itemId = $
我正在阅读How to Make a Javascript Library我发现了作者所说的一个观点: function _() { //Some obects and var
我想用一个新函数扩展“Number”类型,因此我必须定义一个原型(prototype)。当我想到这一点时,我得到了一堆问题: Number 是否既继承了 Object.prototype 又继承了 F
这里好像有区别... 假设我们有 function MyConstructor() {} MyConstructor 的[[Prototype]] 是Function.prototype,不是 MyC
有人建议 Derived.prototype = Object.create(Base.prototype); 优于 Derived.prototype = new Base(); (如 this S
我是一名优秀的程序员,十分优秀!