接口编程的限制

编码是通过接口进行编程时所学的最早和最基本的原理之一。

定义

基于接口的编程将应用程序定义为组件的集合,其中组件之间的应用程序编程接口(API)调用只能通过抽象接口进行,而不能通过具体的类进行。 通常,通过使用Factory模式之类的技术通过其他接口来获取类的实例。

—维基百科
https://zh.wikipedia.org/wiki/基于界面的编程

例如,以下签名不符合标准,因为它使用了具体的类:

<T>ArrayList<T>foo();

合规签名应为:

<T>List<T>foo();

这种设计的基本原理是,调用方不必关心具体的问题,而只关心合同。 因此,提供程序的实现可以更改而不会影响调用者代码。 通过接口进行编程有助于避免连锁反应 ,即在特定位置更改代码库将需要在许多其他位置进行更改。

冰山一角

我在课程中教过它,并且是在代码审查中率先指出它的人之一。 但是,最近,我开始考虑它是否应该像现在这样普遍存在。

回到前面的示例:如果签名引用List ,则实现代码可以返回ArrayListLinkedList或与此相关的符合List任何实现。 它肯定会在所有这些情况下编译 。 但是,切换返回的实现可能会有其他副作用。

您可能知道ArrayList由一个数组支持,而LinkedList由彼此引用的Node对象支持。 根据执行的操作,两者均提供不同的性能结果。

Data structure

Time complexity

Average

Worst

Access

Search

Insertion

Deletion

Access

Search

Insertion

Deletion

Array

θ(1)

θ(n)

θ(n)

θ(n)

O(1)

O(n)

O(n)

O(n)

Doubly-Linked List

θ(n)

θ(n)

θ(1)

θ(1)

O(n)

O(n)

O(1)

O(1)

From http://bigocheatsheet.com/#data-structures

因此,返回的确切内容可能是实现细节,也可能不是。

不只是剪纸

抛弃先前的问题很容易:查看代码并检查实现非常简单。

但是,此检查并不意味着依存关系不会改变。 更糟糕的是,以上示例仅在冰山顶部刷过。 另一个案例涉及OOP的核心原则:

这两个准则自然会导致Decorator模式

装饰图案

例如,让我们使用Cactoos库中Scalar层次结构:

标量

该设计遵循上述原理。 组合不同的Scalar对象非常简单, 例如

Scalarscalar=newStickyScalar<String>(
  newRetryScalar<String>(
    newScalar<String>(){
      @Override
      publicStringgetValue(){
        // Get the value from a network call
      }
    }
  ,3)
);

所有这些嵌套的装饰器层使得很难理解有关值的属性。 例如,在上面的代码片段中,一旦成功读取一次, StickyScalar保留该值。 在下面,有3次尝试从网络读取数据。

仅仅知道一个变量包含Scalar在大多数情况下可能还不够:随着时间的流逝,有些返回相同的值,而有些则没有,等等。

结论

处理抽象而不是混凝土被认为是一种好习惯。 在system-GUI中,最常用的示例是返回一个Window引用,知道它将在Unix系统上是UnixWindow ,而在Windows系统上是WindowsWindow 。 在这种情况下-以及其他一些事情,这是正确的做法。

但是,在其他情况下则不是。 正确管理的类型不是接口,而是更具体的类型。

翻译自: https://blog.frankel.ch/limits-programming-interface/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值