Java 编程到接口意味着什么?
我一直在大多数与编程相关的网站上听到这样的说法: 编程到一个接口,而不是一个 实施 然而,我不明白其中的含义?Java 编程到接口意味着什么?,java,interface,Java,Interface,我一直在大多数与编程相关的网站上听到这样的说法: 编程到一个接口,而不是一个 实施 然而,我不明白其中的含义? 举例会有所帮助 编辑:我已经收到了很多很好的答案,所以你可以用一些代码片段来补充它,以便更好地理解这个主题。谢谢 接口就像是您和接口制作人之间的合同,您的代码将执行他们的请求。此外,您希望以这样一种方式编写代码,即您的解决方案可以多次解决问题。考虑代码重用。当您对实现进行编码时,您只考虑您试图解决的问题的实例。因此,在这种影响下,您的解决方案将不那么通用,而更加集中。这将使编写遵循接口
举例会有所帮助
编辑:我已经收到了很多很好的答案,所以你可以用一些代码片段来补充它,以便更好地理解这个主题。谢谢 接口就像是您和接口制作人之间的合同,您的代码将执行他们的请求。此外,您希望以这样一种方式编写代码,即您的解决方案可以多次解决问题。考虑代码重用。当您对实现进行编码时,您只考虑您试图解决的问题的实例。因此,在这种影响下,您的解决方案将不那么通用,而更加集中。这将使编写遵循接口的通用解决方案更具挑战性。这是一种在模块之间分离责任/依赖关系的方法。 通过定义一个特定的接口(API),您可以确保接口两侧的模块不会相互“打扰” 例如,假设模块1将负责显示特定用户的银行帐户信息,模块2将从使用的“任何”后端获取银行帐户信息 通过定义一些类型和函数以及相关参数,例如定义银行交易的结构,以及一些方法(函数),如GetLastTransactions(AccountNumber、NBTransactionWanted、ArrayToReturnTheSecrec)和GetBalance(AccountNumer),模块1将能够获得所需的信息,不用担心这些信息是如何存储或计算的。相反,Module2将只响应方法调用,按照定义的接口提供信息,但不担心在哪里显示、打印或其他任何信息 更改模块时,接口的实现可能会有所不同,但只要接口保持不变,使用API的模块最坏情况下可能需要重新编译/重建,但无论如何都不需要修改其逻辑
这就是API的概念。本质上,接口是对互操作的一般概念的更具体的表示——它们为您可能需要“插入”的各种选项提供了规范对于一个特定的函数,也应该这样做,这样使用它们的代码就不会依赖于一个特定的选项 例如,许多数据库库充当接口,因为它们可以与许多不同的实际数据库(MSSQL、MySQL、PostgreSQL、SQLite等)一起操作,而使用数据库库的代码根本不需要更改
总的来说,它允许您创建更灵活的代码—为您的客户提供更多关于如何使用它的选项,还可能允许您在多个位置更轻松地重用代码,而不必编写新的专用代码。这句话的核心实际上是关于依赖性的。如果我将类
Foo
编码为一个实现(Bar
而不是IBar
),那么Foo
现在依赖于Bar
。但是如果我将我的类Foo
编码到一个接口(IBar
而不是Bar
),那么实现可能会有所不同,Foo
不再依赖于特定的实现。这种方法提供了一个灵活、松散耦合的代码库,更易于重用、重构和单元测试。通过对接口编程,您更有可能应用低耦合/高内聚原则。
通过编程到一个接口,您可以轻松地切换该接口(特定类)的实现。您可能正在寻找类似以下内容:
public static void main(String... args) {
// do this - declare the variable to be of type Set, which is an interface
Set buddies = new HashSet();
// don't do this - you declare the variable to have a fixed type
HashSet buddies2 = new HashSet();
}
为什么第一种方式被认为是好的?假设稍后您决定需要使用不同的数据结构,例如LinkedHashSet,以便利用LinkedHashSet的功能。代码必须进行如下更改:
public static void main(String... args) {
// do this - declare the variable to be of type Set, which is an interface
Set buddies = new LinkedHashSet(); // <- change the constructor call
// don't do this - you declare the variable to have a fixed type
// this you have to change both the variable type and the constructor call
// HashSet buddies2 = new HashSet(); // old version
LinkedHashSet buddies2 = new LinkedHashSet();
}
这也必须改变
public LinkedHashSet getBuddies() {
return buddies;
}
希望您看到,即使使用这样一个小程序,您对声明变量类型也有深远的影响。由于对象来回移动如此之多,如果您仅仅依赖一个声明为接口的变量,而不是该接口的特定实现(在本例中,将其声明为集合,而不是LinkedHashSet或其他任何形式),那么它肯定有助于使程序更易于编码和维护。可以是这样的:
public Set getBuddies() {
return buddies;
}
还有另一个好处,那就是(至少对我来说)差异帮助我更好地设计程序。但希望我的例子能给你一些想法。。。希望能有所帮助。取一个红色2x4乐高积木,将其连接到一个蓝色2x4乐高积木上,使其中一个积木位于另一个积木之上。现在取下蓝色积木,换上黄色2x4乐高积木。请注意,即使附加块的“实现”不同,红色块也不必更改 现在去买一些其他类型的积木,它不共享乐高“界面”。尝试将其连接到红色2x4乐高上。要做到这一点,你需要改变乐高积木或其他积木,也许可以通过切割一些塑料或添加新的塑料或胶水。请注意,通过更改“实现”,您将被迫更改它或客户端
能够在不改变客户端或服务器的情况下改变实现—这就是编程到接口的意义。这意味着您的变量、属性、参数和返回类型应该具有接口类型,而不是具体的实现 这意味着您可以使用
IEnumerable Foo(IList mylist)
而不是ArrayList Foo(ArrayList mylist)
仅在构造对象时使用实现:
IList list = new ArrayList();
如果你这样做了
IList list = new ArrayList();
Vector items = new Vector();
// fill it
Object first = items.firstElement();
ArrayList items = new ArrayList();
// fill it
Object first = items.firstElement(); // compile time error.
List items = new Vector();
// fill it
Object first = items.get( 0 ); //
List items = new ArrayList(); // Or LinkedList or any other who implements List
// fill it
Object first = items.get( 0 ); // Doesn't break
statement.executeOracle9iSomething();
statement.executeOracle11gSomething();
if (dataType == "XML")
{
... read a piece of XML data ...
}
else
{
.. query something from the SQL database ...
}
interface IDoor
{
void Open();
void Close();
}
class BackwardDoor : IDoor
{
public void Open()
{
// code to make the door open the "wrong way".
}
public void Close()
{
// code to make the door close properly.
}
}
class RegularDoor : IDoor
{
public void Open()
{
// code to make the door open the "proper way"
}
public void Close()
{
// code to make the door close properly.
}
}
class RedUkTaxiDoor : BackwardDoor
{
public Color Color
{
get
{
return Color.Red;
}
}
}
class DoorRepairer
{
public void Repair(IDoor door)
{
door.Open();
// Do stuff inside the car.
door.Close();
}
}
DoorRepairer repairer = new DoorRepairer();
repairer.Repair( new RegularDoor() );
repairer.Repair( new BackwardDoor() );
repairer.Repair( new RedUkTaxiDoor() );
class ListAdder
{
public void PopulateWithSomething(IList list)
{
list.Add("one");
list.Add("two");
}
}
Stack stack = new Stack();
Queue queue = new Queue();
ListAdder la = new ListAdder()
la.PopulateWithSomething(stack);
la.PopulateWithSomething(queue);
class Printer
{
public void PrintCat(Cat cat)
{
...
}
public void PrintDog(Dog dog)
{
...
}
...
}
class Printer
{
public void Print(Printable p)
{
Bitmap bitmap = p.GetBitmap();
// print bitmap ...
}
}