Java基础 :"面向接口的编程方式"

码前小故事

《宠物车运送宠物的风流韵事》

假设当前,有一个Pet类,一个Dog类,一个Cat类,一个宠物袋类PetBag类,一个宠物车类PetCar。

业务逻辑是这样的:
我们需要将宠物装进宠物袋,然后放进宠物车进行管理并运输。而我们希望宠物类与宠物车类都尽量独立低耦合度,因为这些宠物日后运输到目的地后就与宠物车毫无联系了,而是与新家发生联系。我们也希望宠物车不了解宠物,因为他的工作时运输每一个装着宠物的宠物袋,而宠物袋装的是阿猫阿狗蜥蜴仓鼠等都没关系,因为每个宠物都被宠物袋隔离保护起来,宠物车不需要担心他们被对方吃掉而了解他们并管理他们。

于是,宠物和宠物车之间的联系,就建立在宠物袋之上。那么,宠物车只要确定被送进来的是宠物袋,而不是其他物体即可。但我们实际上要送上车的是宠物,而宠物不是宠物袋,怎么办呢?这时,我们就需要更抽象的思想,我们只要让宠物车认为并接受宠物是宠物袋(Is - a 关系),那么宠物不就可以上车了?

这样,我们就不需要单独实现一个宠物袋类实例化一个宠物袋的对象,把宠物对象先装入宠物袋,再送上车了,而是直接让宠物告诉宠物车我是宠物袋的就可以上车了。但我们还是需要有宠物袋的隔离功能,不然宠物车还是要去学习(方法)怎么去让不同的宠物安分下来

所以,接口的概念变得有意了。把宠物袋类改成一个接口,让宠物类实现该接口,让宠物车了解宠物袋接口(拥有宠物袋接口的变量),那么宠物就可以上车(把宠物对象引用赋给宠物车里面的宠物袋变量),而宠物袋接口是有管理隔离宠物的功能的(接口方法),宠物实现了宠物袋的接口,就学会了如何管理隔离。那么,问题就轻松解决了。

日后动物不再上车了,就把就把接口去掉,内部代码则不需要修改,还是原原本本干干净净的狗狗,不谙世事,不知外面世界的纷繁复杂,保留了更多的重用性,被其他程序利用

而宠物车负责运算宠物袋的职责也始终如一,日后我们说不定可以在宠物袋里面装玉米香蕉呢,那么宠物车又多了一个新业务,而不需要改动代码,只需要玉米香蕉实现宠物袋的接口就行了,香蕉玉米也不用知道自己居然被宠物车接送这么悲催的现实!


知识点

Java把抽象的概念又更推进了一步 :接口(Interface)

接口规定了长什么样能干什么,但不管里面具体怎么实现。接口其实就是完全抽象的类,因此接口和类的地位是一样的,此前所有针对类的所有法则同样适用于接口。因此我们可以看到其定义方式跟类也是基本上一样的。当然,其中的所有方法都没有方法体。

(补充:interface允许有static,abstractdefault(非static、abstract)方法。静态方法无需实例化,直接可用。Java 1.8中,增加了default方法,提供接口的默认实现。)

当类从接口得到继承的时候,Java用另外一个动词:实现(implements)。当然,实现接口的类必须覆盖接口中所有的方法,否则这个类要作为一个抽象类。

Java不允许多继承,但是允许多实现
两准两不准:
- 准:允许一个类实现多个接口
- 准:也允许一个接口从多个接口得到继承
- 不准:但是不允许接口从类继承
- 不准:也不允许接口实现接口。

  • 接口方法 public abstract
  • 可以有公开静态常量 public static final

前言所述业务的核心代码示例

接口是纯抽象类。接口所有成员函数全是抽象函数,所有的方法都是没有方法体的,而且都是默认并强制被声明为public abstract,即使你没有这样声明(啥声明关键字都没写)。

//定义一个只有抽象成员函数的接口PetBag
public interface PetBag{
       public abstract void insulate( );
}

所有成员变量都是public static final的变量,并且必须有定义初始化,因为所有变量都必须在编译的时候有确定值
public static final --- 表示 : 该变量不属于任何对象,仅属于类,且是常量

//定义一个有抽象成员函数和静态不可变的成员变量的接口PetBag
public interface PetBag{
       public static final String SIZE = "Large";
       public abstract void insulate( );
}

实现接口 继承了Pet的Cat、Dog等萌死人不偿命星球来的小动物就可以被PetBag的变量管理了。

public class Cat extends Pet implements PetBag{
      ......
      @Override
      public void insulate( );
}

使用接口编程 在PetCar中通过PetBeg来管理Cat对象。

public class PetCar{
    private List<PetBag> pets = new ArrayList<PetBag>();
    public addPet(PetBag pet){
          pets.add(pet);
    }
    public static void main(String[] args){
          PetCar petCar = new PetCar();
          PetBag cat = new Cat();
          petCar.addPet(cat);
          ...
    }
} 

小结

面向接口的编程方式
  1. “定义接口 — 定义类” —> 先定义接口,再实现类
  2. 任何需要在函数间传入传出的参数一定是接口而不是具体的类
  3. 面向接口的编程方式是Java成功关键之一,因为—>极适合多人同时写一个大程序
    一方只认识接口,想要进入那一方,就披上那个接口外套吧。

注意

问题
  • 因为接口里面的方法没有方法体,要是我想每个实现了接口的类里面的方法体都一样,咋办呢?要是每个类实现接口的函数都粘贴复制一遍,不就不符合面向对象的编程思路了吗?

    策略模式: 暂时想到的,定义一个类,里面实现一个方法。把该类的实例对象作为参数传给接口的抽象方法。而实现接口的类在实现的方法体里面通过对象变量执行对象的类里面的方法即可。这样方法逻辑只需写一次,在其他实现类里面通过对象调用就好。


  • 设计:两个类的关系,在A类中的大量操作都用到了B类的数据,我们该如何设计呢?

    方法一:
    让A类拥有一个B类对象的管理者(A是知到B的):传一个this
    方法二:
    由外部第三方来建立两者之间的联系(A不知道B)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忘词木头人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值