考虑下面的类层次结构在复杂层次注射运行时依赖抽象工厂
- ClassA的需要ClassB的
- ClassB的需要ClassC
我们得到了一个依赖关系图如下:
ClassA --> ClassB --> ClassC
所以如果我们使用DI,我们将ClassC和ClassB注入到ClassA中。
但是现在让我们假设ClassC是一个运行时依赖项(例如某种策略)。建议的方式注入运行时的依赖是引入一个抽象工厂就像一个
ClassCFactory
现在我们可以注入ClassCFactory到ClassB的,并得到如下图
ClassA --> ClassB --> ClassCFactory
现在我们有一个方法ClassB的其中我们可以打电话让工厂做好工作。例如
ObjB.SelectC(MyRuntimeValue)
但是现在在我们的应用中,我们不知道什么ClassB的(或许还有一些涉及更多层)。一种解决方案可能是有SelectC在ClassA的
ObjA.SelectC(MyRuntimeValue) -(calls)-> ObjB.SelectC(MyRuntimeValue)
,或者我们干脆违反法律德米特和做类似
ObjA.ObjB.SelectC(MyRuntimeValue)
我认为每个人都同意,第二个解决方案是不是要走的路。但第一个解决方案也有一些缺点,特别是如果我们之间有更多的层。
我们也可以拉出工厂的一个层次来创建ClassB,但是ClassB真的是运行时的依赖关系吗? 你建议什么解决方案?或者它甚至是一个糟糕的课程设计?
恕我直言,总是更好地依赖于对象实际需要做的工作,而不是创建所需对象的工厂。但有了这个想法一记DI容器将是无用的...
好的,我会给你更具体的含义:ClassC是一个抽象类Encrytption,它对不同类型的加密有不同的实现。 ClassB是一个装饰器,用Encryption装饰FileStream。而ClassA是某种可序列化的对象,需要序列化一个流。 – 2013-03-26 10:43:17
什么决定使用哪种类型的加密?您可以让ClassA的消费者决定并将3个俄罗斯娃娃放在一起(加密,FileStreeamDecorator和ClassA),或者一些外部对象可以选择一个加密,将其放入FileStreamDecorator并将其全部传递给ClassA的消费者......真的取决于您的上下文。 – guillaume31 2013-03-26 11:28:52
选择正确的加密取决于我们加载或我们保存。加载时,我们询问标题,使用哪种加密,然后我们询问用户密码并开始阅读和解密。在保存时,我们必须使用与加载时相同的加密。有一种特殊的导出方式,用户最终可以决定使用哪种加密方式。 – 2013-03-26 11:54:56