让我们创建一个虚拟的例子。
A套餐类别
packageA:
package packageA;import packageB.B;public class A { private B myB; public A() { this.myB = new B(); } public void doSomethingThatUsesB() { System.out.println("Doing things with myB"); this.myB.doSomething(); }}
B套餐类别
packageB:
package packageB;public class B { public void doSomething() { System.out.println("B did something."); }}
如我们所见,
A取决于
B。没有
B,
A则不能使用。但是,如果
B将来我们想用a
代替
BetterB呢?对于这一点,我们创建了一个界面
Inter内
packageA:
package packageA;public interface Inter { public void doSomething();}
为了利用这个界面,我们
import packageA.Inter;
让B implements Inter
中B
和- 用替换所有
B
内部的A
出现Inter
。
结果是该版本的修改版
A:
package packageA;public class A { private Inter myInter; public A() { this.myInter = ???; // What to do here? } public void doSomethingThatUsesInter() { System.out.println("Doing things with myInter"); this.myInter.doSomething(); }}
我们已经看到,从
A到的依赖关系
B消失了:
importpackageB.B;不再需要。仅存在一个问题:我们无法实例化接口的实例。但是控制反转才是真正的解决方案:与其
Inter在
A构造函数中实例化某种类型的东西,构造器将需要一些
implementsInter作为参数的东西:
package packageA;public class A { private Inter myInter; public A(Inter myInter) { this.myInter = myInter; } public void doSomethingThatUsesInter() { System.out.println("Doing things with myInter"); this.myInter.doSomething(); }}
通过这种方法,我们可以改变现在的具体实施
Inter中
A随意。假设我们编写了一个新类
BetterB:
package packageB;import packageA.Inter;public class BetterB implements Inter { @Override public void doSomething() { System.out.println("BetterB did something."); }}
现在我们可以
A使用不同的
Inter实现实例化:
Inter b = new B();A aWithB = new A(b);aWithB.doSomethingThatUsesInter();Inter betterB = new BetterB();A aWithBetterB = new A(betterB);aWithBetterB.doSomethingThatUsesInter();
而且我们不必更改其中的任何内容
A。现在,代码已解耦
Inter,只要满足了合同,我们就可以随意更改的具体实现
Inter。最值得一提的是,我们可以支持将在以后编写并实现的代码
Inter。
附录
我两年多以前写了这个答案。在总体上对答案感到满意的同时,我始终以为缺少了一些东西,我想我终于知道了那是什么。以下内容对于理解答案不是必需的,而是旨在引起读者的兴趣,并为进一步的自我教育提供一些资源。
在文献中,这种方法被称为接口隔离原理,属于
SOLID
原理。YouTube上Bob叔叔有一个很好的演讲(有趣的一点是大约15分钟长),展示了如何使用多态和接口使编译时依赖点指向控制流(建议观看者酌情决定,Bob叔叔将关于Java的轻描淡写。相应地,这意味着当高层实现通过接口隔离时,不需要高层实现。因此,如上所述,可以随意交换较低的级别。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)