Java &引用;编程到一个接口";。这是什么意思?
可能重复:Java &引用;编程到一个接口";。这是什么意思?,java,oop,Java,Oop,可能重复: 我经常遇到这个词: 编程到一个接口 这到底是什么意思?一个真实的设计场景将受到高度赞赏。我认为这是Erich Gamma的咒语之一。我找不到他第一次描述它(在GOF书之前),但你可以在采访中看到它的讨论:“编程到接口”发生在你使用库时,你在自己的代码中依赖的其他代码。然后,其他代码向您表示自身的方式、方法名称、参数、返回值等构成了您必须编程的接口。这是关于如何使用第三方代码的 这也意味着,您不必关心所依赖的代码的内部结构,只要接口保持不变,您的代码就是安全的(好吧,或多或少…) 从
我经常遇到这个词: 编程到一个接口
这到底是什么意思?一个真实的设计场景将受到高度赞赏。我认为这是Erich Gamma的咒语之一。我找不到他第一次描述它(在GOF书之前),但你可以在采访中看到它的讨论:“编程到接口”发生在你使用库时,你在自己的代码中依赖的其他代码。然后,其他代码向您表示自身的方式、方法名称、参数、返回值等构成了您必须编程的接口。这是关于如何使用第三方代码的 这也意味着,您不必关心所依赖的代码的内部结构,只要接口保持不变,您的代码就是安全的(好吧,或多或少…) 从技术上讲,还有更精细的细节,比如Java中称为“接口”的语言概念
如果你想了解更多,你可以问“实现接口”是什么意思…现实世界的例子很实用。其中一项: 对于JDBC,您使用的是接口
java.sql.Connection
。但是,每个JDBC驱动程序都提供自己的连接实现。您不必知道关于特定实现的任何信息,因为它符合连接
接口
另一个来自java集合框架。有一个java.util.Collection
接口,它定义了size
、add
和remove
方法(以及许多其他方法)。因此,您可以互换地使用所有类型的集合。假设你有以下几点:
public float calculateCoefficient(Collection collection) {
return collection.size() * something / somethingElse;
}
还有另外两个调用这个的方法。另一种方法使用LinkedList
,因为它更高效,而另一种方法使用TreeSet
由于LinkedList
和TreeSet
都实现了Collection
接口,因此只能使用一种方法来执行系数计算。不需要复制您的代码
这里是“编程到接口”-您不关心size()
方法的具体实现方式,您知道它应该返回集合的大小-也就是说,您已经编程到集合
接口,而不是链接列表
和树集
但是我的建议是找一本书来阅读——比如说一本书(“用Java思考”),书中详细解释了这个概念。每个对象都有一个公开的接口。集合有添加
,删除
,在
等。套接字可能有发送
,接收
,关闭
等
实际上,每个可以获得引用的对象都有这些接口的具体实现
这两件事都是显而易见的,但不太明显的是
您的代码不应依赖于对象的实现细节,而应依赖于其发布的接口。
如果你把它发挥到极致,你只需要针对Collection
等进行编码(而不是ArrayList
)。更实际地说,只需确保可以在不破坏代码的情况下交换概念上相同的内容
要敲出集合
示例:您有一个某物的集合,实际上您正在使用ArrayList
,因为为什么不这样做。如果将来使用LinkedList
,你应该确保你的代码不会被破坏。这基本上意味着你要使用的库中唯一应该依赖的部分是它的API(应用程序编程接口)您不应该将应用程序建立在库的具体实现之上
假设你有一个能给你一个堆栈的库。这个类提供了几个方法。比如说push
,pop
,isempty
和top
。您应该仅依靠这些来编写应用程序。违反这一点的一种方法是查看内部,发现堆栈是使用某种数组实现的,这样,如果从空堆栈中弹出,就会得到某种索引异常,然后捕获它,而不是依赖类提供的isempty
方法。如果库提供者从使用数组切换到使用某种列表,而后者仍然工作,假设提供者保持API仍在工作,则前者的方法将失败 多态性取决于对接口的编程,而不是实现
仅根据抽象类定义的接口操作对象有两个好处:
只要对象符合客户机期望的接口,客户机就不知道他们使用的对象的特定类型
客户端仍然不知道实现这些对象的类。客户端只知道定义接口的抽象类
这大大减少了子系统之间的实现依赖性,从而产生了对接口进行编程的原则
有关此设计的进一步说明,请参见
资料来源:G.O.F
另请参见:,简单地说,不要以这样的方式编写类
我依靠这个班来完成我的工作
你写的方式是这样的
我依靠任何做这些事情的班级来完成我的工作
第一个示例表示一个依赖于特定具体实现来完成其工作的类。从本质上来说,这不是很灵活
第二个示例表示写入接口的类。它不关心你使用什么具体的对象,它只关心它的实现
interface IDrivable
{
void accelerate();
void brake();
}
class Car implements IDrivable
{
void accelerate()
{ System.out.println("Vroom"); }
void brake()
{ System.out.println("Queeeeek");}
}
class Bike implements IDrivable
{
void accelerate()
{ System.out.println("Rattle, Rattle, ..."); }
void brake()
{ System.out.println("..."); }
}
List<IDrivable> vehicleList = new ArrayList<IDrivable>();
list.add(new Car());
list.add(new Car());
list.add(new Bike());
list.add(new Car());
list.add(new Bike());
list.add(new Bike());
for(IDrivable vehicle: vehicleList)
{
vehicle.accelerate(); //this could be a bike or a car, or anything that implements IDrivable
}