How to convert this code so it now uses the Dependency Injection pattern?
好的,我有以下情况。我最初有一些这样的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
现在,我决定重构代码,以便注入类的依赖项,而不是:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class MainBoard { private IBoardType1 bt1; private IBoardType2 bt2; private IBoardType3 bt3; ... private Size boardSize; public MainBoard(Size boardSize, IBoardType1 bt1, IBoardType2 bt2, IBoardType3 bt3) { this.bt1 = bt1; this.bt2 = bt2; this.bt3 = bt3; } } |
我的问题是如何处理电路板尺寸?我的意思是,在第一种情况下,我只是通过了班级所需的董事会规模,它将尽一切努力创造其他类型的董事会与正确的规模。在依赖注入的情况下,情况可能不会更糟。你们在这种情况下做什么?您是否对
我为什么要这样做?因为我需要单元测试主板。我需要能够在特定的状态下设置3个子板,这样我就可以测试我的主板在做我期望的事情。
谢谢
型
在第二种情况下,我会说
但总的来说,第二个案例对我来说是可疑的。我建议采用第一种方法,除非您确实需要向主板注入不同类型的主板。即便如此,我还是会考虑使用一个电路板工厂,而不是将3个电路板参数传递给构造函数,例如。
1 2 3 4 5 | public interface IBoardBuilderFactory { public IBoardType1 createBoardType1(Size boardSize); public IBoardType2 createBoardType2(Size boardSize); public IBoardType3 createBoardType3(Size boardSize); } |
这将确保3块电路板在"电路板系列"和尺寸方面的一致性。
我们应该更多地了解上下文/域模型,特别是主板和子主板的关系,以便决定DI是否是这里的正确选择。
型
在这种情况下,是否应该应用依赖注入(或依赖倒置)是值得怀疑的。在我看来,您的
这是在消费者方面的灵活性和附加义务之间的权衡。
另一方面,如果从外部处理
依赖性注入的主要优点是隔离被注入对象的变化。所以在你的例子中,一个明显的变量就是大小。你将把这些板注入主板,这样主板就不再需要知道或担心尺寸了。另外,除非应用程序需要在不同的板类型之间维护3种不同的行为,否则我建议对板类型接口使用一个抽象定义。
1 2 3 4 5 6 7 8 9 10 11 | public class MainBoard { private IBoardType bt1; private IBoardType bt2; private IBoardType bt3; public MainBoard(IBoardType bt1, IBoardType bt2, IBoardType bt3) { this.bt1 = bt1; this.bt2 = bt2; this.bt3 = bt3; } } |
它成为执行注入(注入框架或组装代码)的事情的责任,以确保这些板被赋予适当的大小。这可以通过多种方式实现,一个例子是主板和注入板都是从一个外部源获得它们的大小。也许你的应用程序,在这种情况下,尺寸注入板相对于主板。
所以你可以有外部逻辑,比如:
1 2 3 4 5 6 |
本质上,您所追求的是在构建主板的任何地方对构建逻辑进行反转。从那里开始,把所有的东西都提取到一个工厂或者某个邪恶的单体工厂或者静态方法中。问问自己,"主板是在哪里创建的?"还要问,"需要什么组件和参数?"一旦将所有实例化逻辑移入工厂,维护主板及其所有依赖项可能会变得更简单。
型
-编辑-删除了我的大部分回复,因为其他人击败了我:)
另一个选择是工厂。根据您的需求,您可能会发现使用工厂来解决您的问题更好(或更好)。这里有一个关于工厂和DI的很好的讨论。您甚至可以考虑通过DI将factroy传递到类构造函数中——因此,您的构造函数采用大小和工厂类,并遵从工厂类(传递大小)来获取板。
型
1 2 3 4 5 6 7 8 9 10 11 12 | public class MainBoard { private IBoardType1 bt1; private IBoardType2 bt2; private IBoardType3 bt3; ... private Size boardSize; public MainBoard(IBoardBuilderFactory factory) { this.bt1 = factory.buildBoard(boardSize); //... } } |
号
如果板的尺寸是由外部决定的,也许你根本不储存它。也许工厂决定在别处建造时使用什么尺寸的电路板。
总之,关键是,设计模式可以帮助您以一种干净和可维护的方式完成任务。他们不是必须遵守的硬性规定。
在
1 2 | int boardSize = 24; // Or maybe you get this from reading a file or command line MainBoardScope mainBoardScope = new mainBoardScope( boardSize ); |
如果您天真地将24设置为全局或常量,那么在这里很难看到依赖项,因为类将依赖于静态地获取该常量或全局,而不是通过声明的接口(即构造函数)。
1 2 | MainBoardFactory factory = new MainBoardFactory( mainBoardScope ); MainBoard board = factory.createMainBoard(); |
在该
1 2 3 4 | IBoardType1 b1 = injectBoardType1( myScope ); IBoardType2 b2 = injectBoardType2( myScope ); IBoardType3 b3 = injectBoardType3( myScope ); return new MainBoard( scope.getBoardSize, b1, b2, b3 ); |
您是否需要主板来检查传递给建设者的三个主板的大小是否正确?如果是您的代码创建板,那么为
型
您可以有一个boardtypefactory来创建这样的boardtypes:
江户十一〔九〕号
请注意,有大量的博客文章,所以回答如何最好地写一个工厂,上面是一个简单的例子。
然后你可以打电话
埃多克斯1〔10〕
传递用于创建板的源大小。
型
您可以从一个经过DI的板中获得板大小。这样就可以将boardsize变量放在一起。