到底面向?编程

面向过程编程(Procedure Oriented、简称PO面向对象编程(Object Oriented、简称OO 我们一定听过,然而实际企业级开发里受用更多的一种编程思想那就是:面向接口编程(Interface-Oriented

接口这个概念我们一定不陌生,实际生活中最常见的例子就是:插座!

我们只需要事先定义好插座的接口标准,各大插座厂商只要按这个接口标准生产,管你什么牌子、内部什么电路结构,这些均和用户无关,用户拿来就可以用;而且即使插座坏了,只要换一个符合接口标准的新插座,一切照样工作!

同理,实际代码设计也是这样!

我们在设计一个软件的代码架构时,我们都希望事先约定好各个功能的接口(即:约定好接口签名和方法),实际开发时我们只需要实现这个接口就能完成具体的功能!后续即使项目变化、功能升级,程序员只需要按照接口约定重新实现一下,就可以达到系统升级和扩展的目的!

正好,Java中天生就有interface这个语法,这简直是为面向接口编程而生的!

所以接下来落实到代码上,举个通俗一点的小例子唠一唠,实际业务代码虽然比这个复杂,但原理是一模一样的。


做梦了

假如哪一天程序羊真发达了,一口豪气买了两辆豪车,一辆五菱宏光、一辆飞度、并且还专门聘请了一位驾驶员来帮助驾驶。

两辆豪车在此:

public class Wuling {public void drive() {System.out.println("驾驶五菱宏光汽车");}
}public class Fit {public void drive() {System.out.println("驾驶飞度汽车");}
}

驾驶员定义在此:

驾驶员定义了两个drive()方法,分别用来驾驶两辆车:

public class Driver {public void drive( Wuling wuling ) {wuling.drive(); // 驾驶五菱宏光的方法}public void drive( Fit fit ) {fit.drive();    // 驾驶飞度的方法}// 用于测试功能的 main()函数public static void main( String[] args ) {// 实例化两辆新车Wuling wuling = new Wuling();Fit fit = new Fit();// 实例化驾驶员Driver driver = new Driver();driver.drive( wuling ); // 帮我开五菱宏光driver.drive( fit );    // 帮我开飞度}
}

这暂且看起来没问题!日子过得很融洽。

但后来过了段时间,程序羊又变得发达了一点,这次他又豪气地买了一辆新款奥拓(Alto)!

可是现有的驾驶员类Driver的两个drive()方法里都开不了这辆新买的奥拓该怎么办呢?


代码的灵活解耦

这时候,我想应该没有谁会专门再去往Driver类中添加一个新的drive()方法来达到目的吧?毕竟谁也不知道以后他还会不会买新车!

这时候如果我希望我聘请的这位驾驶员对于所有车型都能驾驭,该怎么办呢?

很容易想到,我们应该做一层抽象。毕竟不管是奥拓还是奥迪,它们都是汽车,因此我们定义一个父类叫做汽车类Car,里面只声明一个通用的drive()方法,具体怎么开先不用管:

// 抽象的汽车类Car,代表所有汽车
public class Car {void drive() { } // 通用的汽车驾驶方法
}

这时,只要我新买的奥拓符合Car定义的驾驶标准即可被我的驾驶员驾驶,所以只需要新的奥拓来继承一下Car类即可:

public class Alto extends Car {public void drive() {System.out.println("驾驶奥拓汽车");}
}

同理,只需要我的驾驶员具备通用汽车Car的驾驶能力,那驾驶所有的汽车都不是问题,因此Drvier类的drive()方法只要传入的参数是父类,那就具备了通用性:

public class Driver {public void drive( Car car ) {  // 方法参数使用父类来替代car.drive();}public static void main( String[] args ) {Alto alto = new Alto();Driver driver = new Driver();driver.drive( alto );}
}

问题暂且解决了!


但是再后来,程序羊他好像又更发达了一些,连车都不想坐了,想买一头驴(Donkey)让司机骑着带他出行!

很明显,原先适用于汽车的drive()方法肯定是不适合骑驴的!但我们希望聘请的这位驾驶员既会开汽车,又会骑驴怎么办呢?

害!我们干脆直接定义一个叫做交通工具(TrafficTools)的通用接口吧!里面包含一个通用的交通工具使用方法,管你是驾驶汽车,还是骑驴骑马,具体技能怎么实现先不管:

// 通用的交通工具接口定义
public interface TrafficTools {void drive();  // 通用的交通工具使用方法
}

有了这个接口约定,接下来就好办了。我们让所有的Car、或者驴、马等,都来实现这个接口:

public class Car implements TrafficTools {@Overridepublic void drive() { }
}public class Wuling extends Car {public void drive() {System.out.println("驾驶五菱宏光汽车");}
}public class Fit extends Car {public void drive() {System.out.println("驾驶飞度汽车");}
}public class Alto extends Car {public void drive() {System.out.println("驾驶奥拓汽车");}
}public class Donkey implements TrafficTools {@Overridepublic void drive() {System.out.println("骑一头驴");}
}

这个时候只要我们的驾驶员师傅也面向接口编程,就没有任何问题:

public class Driver {// 方法参数面向接口编程public void drive( TrafficTools trafficTools ) {trafficTools.drive();}public static void main( String[] args ) {Driver driver = new Driver();driver.drive( new Wuling() );  // 开五菱driver.drive( new Fit() );     // 开飞度driver.drive( new Alto() );    // 开奥拓driver.drive( new Donkey() );  // 骑一头驴}
}

很明显,代码完全解耦了!这就是接口带来的便利。


代码的扩展性

面向接口编程的优点远不止上面这种代码解耦的场景,在实际企业开发里,利用接口思想对已有代码进行灵活扩展也特别常见。

再举一个例子:假设程序羊有一个非常豪气的朋友,叫:程序牛,他们家出行可不坐车,全靠私人飞机出行:

// 通用的飞机飞行接口
public interface Plane {void fly();
}// 程序牛的专用机长,受过专业训练(即:实现了通用飞行接口)
public class PlaneDriver implements Plane {@Overridepublic void fly() {System.out.println("专业的飞行员操控飞机");}
}// 出门旅行
public class Travel {// 此处函数参数也是面向接口编程!!!public void fly( Plane plane ) {plane.fly();}public static void main( String[] args ) {Travel travel = new Travel();  // 开启一段旅行PlaneDriver planeDriver = new PlaneDriver(); // 聘请一个机长travel.fly( planeDriver ); // 由专业机长开飞机愉快的出去旅行}
}

但是突然有一天,他们家聘请的机长跳槽了,这时候程序牛一家就无法出行了,毕竟飞机不会驾驶。

于是他跑来问我借司机,想让我的驾驶员来帮他驾驶飞机出去旅行。

我一看,由于他们的代码面向的是接口,我就肯定地答应了他!

这时候对我这边的扩展来说就非常容易了,我只需要安排我的驾驶员去培训一下飞行技能就OK了(实现一个方法就行):

// 让我的驾驶员去培训一下飞行技能(即:去实现通用飞行接口)
public class Driver implements Plane {public void drive( TrafficTools trafficTools ) {trafficTools.drive();}// 实现了fly()方法,这下我的驾驶员也具备操控飞机的能力了!@Overridepublic void fly() {System.out.println("普通驾驶员操控飞机");}
}

这时候我的驾驶员Driver类就可以直接服务于他们一家的出行了:

public class Travel {public void fly( Plane plane ) {plane.fly();}public static void main( String[] args ) {Travel travel = new Travel();// 专业飞行员操控飞机PlaneDriver planeDriver = new PlaneDriver();travel.fly( planeDriver );// 普通驾驶员操控飞机Driver driver = new Driver();travel.fly( driver );}
}

看到没,这一改造过程中,我们只增加了代码,却并没有修改任何已有代码,就完成了代码扩展的任务,非常符合开闭原则


实际项目

实际开发中,我们就暂且不说诸如Spring这种框架内部会大量使用接口,并对外提供使用,就连我们自己平时写业务代码,我们也习惯于在Service层使用接口来进行一层隔离:

这种接口定义和具体实现逻辑的分开,非常有利于后续扩展和维护!


小结

面向接口编程开发,对代码架构的解耦和扩展确实很有好处,这种编码思想也值得平时开发结合实践反复理解和回味!

为什么我们要面向接口编程?!相关推荐

  1. 【转】工厂模式面向接口编程

    为了实现更好的灵活性     应改面向接口编程.因此,应该面向接口提供工场.         比如,Cat,   Dog,   Mouse,都是4条腿会跑的动物.     因此,我们建立一个接口叫做F ...

  2. 黑马java教程是什么_Java教程:揭秘什么是面向接口编程

    先用一个案例来给大家说明一下面向接口编程. 案例:有一个电脑类(Computer),电脑除了有基本的开机关机功能外,还有连接任何外接设备的功能,比如能电脑能连接外置键盘(Keyboard),鼠标(Mo ...

  3. Java面向接口编程,低耦合高内聚的设计哲学

    接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极大的降低程序中各个模块之间的耦合,提高系统的可维护性以及可扩展性. 因此,很多的软件架构设计理念都倡导"面向接口编程"而 ...

  4. java的知识点13——多态、对象的转型(casting)、final关键字、抽象方法和抽象类、接口的作用、如何定义和使用接口?、接口的多继承、面向接口编程

    多态 多态指的是同一个方法调用,由于对象不同可能会有不同的行为.现实生活中,同一个方法,具体实现会完全不同. 多态的要点: 1. 多态是方法的多态,不是属性的多态(多态与属性无关). 2. 多态的存在 ...

  5. Java 面向抽象编程和面向接口编程

    以下内容来自<Java 2实用教程>,主编:耿祥义.张跃平 鉴于面向抽象编程和面向接口编程思维培养的重要性,写此博客巩固. 面向抽象编程: 在设计程序时,经常会使用到abstract类,其 ...

  6. 为什么有人说面向对象编程就是面向接口编程?

    "面向对象编程就是面向接口编程" 这句话相信, 很多人都在网上见过, 装b利器. 我一开始也是这么想的, 那些装b者丢下这一句, 就没下文了. 首先, 我认为这句话是1个假命题. ...

  7. python面向接口编程_Python 中的面向接口编程

    前言 "面向接口编程"写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性.维护性谁都不能拒绝 ...

  8. C语言面向对象编程(四):面向接口编程

    Java 中有 interface 关键字,C++ 中有抽象类或纯虚类可以与 interface 比拟,C 语言中也可以实现类似的特性. 在面试 Java 程序员时我经常问的一个问题是:接口和抽象类有 ...

  9. python 接口编程_Python 中的面向接口编程

    前言 "面向接口编程"写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性.维护性谁都不能拒绝 ...

  10. 软件设计模式—面向接口编程

    原文作者:laoer2009 原文地址:设计模式之面向接口编程 01第一次需求 玩家有很多属性,例如:身高,性别 blalalala ,玩家可以攻击其他玩家.产品狗YY妹子写程序也是很利索,一天就把程 ...

最新文章

  1. R语言构建回归模型并进行模型诊断(线性关系不满足时)、进行变量变换(Transforming variables)、使用car包中的boxTidwell函数对预测变量进行Box–Tidwell变换
  2. VS2008下利用#pragma comment屏蔽VC/VS生成的exe程序的CMD窗口
  3. Oracle Discover产品简介
  4. 动态代理源码分析,实现自己的动态代理
  5. Entity Framework 简介
  6. Linux无线网卡的工作模式
  7. oracle 不包含某个单词,SQL SELECT WHERE字段包含单词
  8. 开源压缩算法brotli_Google的Brotli压缩算法,C ++核心准则以及更多新闻
  9. python简单代码需要写多久_python基本语法?初学Python要多久才能入门?
  10. 面试官: Flink双流JOIN了解吗? 简单说说其实现原理
  11. 在线火星文转换器工具
  12. [自己动手玩黑科技] 1、小黑科技——如何将普通的家电改造成可以与手机App联动的“智能硬件”...
  13. Python实现(百度地图API)地理编码与逆地理编码
  14. Halcon 注册说明
  15. win linux批处理删除指定N天前文件夹的文件
  16. 固态硬盘重装系统后进入老系统找东西
  17. 每日一课 | python烤地瓜案例
  18. 幂指函数的求导方法, 了解对数恒等式的定义
  19. centos安装unrar并使用
  20. Lattice Mico8在LMS上中断错误问题

热门文章

  1. Constraintlayout 2.0:你们要的更新来了
  2. 儿保系统软件有哪些?
  3. gitlab配置公钥
  4. Intel Quartus Prime 安装激活 IP License大全 3339377509@qq.com
  5. ERROR com.alibaba.druid.pool.DruidDataSource - abandon connection, open stackTrace: 已解决
  6. 狂热的商城和被弃的淘宝
  7. UDS诊断系列之十 DTC控制(85)服务
  8. android gif播放卡顿,PhotoView播放gif卡顿
  9. 理解分布式一致性:Paxos协议之Basic Paxos
  10. 超详细shell脚本编程快速入门