引例
顾客去移动大厅办理业务,可提供的套餐如下:
| 套餐 | 话唠套餐 | 网虫套餐 | 超人套餐 |
|---|---|---|---|
| 通话时长(分钟) | 500分钟 | / | 200分钟 |
| 上网流量(GB) | / | 10GB | 5GB |
| 短信(条) | 30条 | / | 50条 |
| 资费(元/月) | 58元/月 | 68元/月 | 78元/月 |
(1)类的设计-封装
(2)优化设计-继承
从类图可以看出,打电话、发短信、上网三个方法存在多个子类中,也需要抽象成父类方法,但三个方法不能写在同一个父类中,如果三个方法都写在同一个父类中,它的子类就把三个方法都继承下来了,这样任何一个套餐都具有打电话、发短信和上网的功能。如何设计呢?可以将三个方法分别设计成三个父类,然后由子类去继承。那么问题来了,一个子类只能继承一个父类(单根性),子类如何能继承多个父类呢?用接口可以解决多继承的问题。
一、什么是接口
接口:就是多个类的公共规范,能更好的扩展程序的功能,可以将程序模块像组件一样任意装卸。像USB接口是一种规范,手机充电器接口也是一种规范,规定了接口的大小、开关、电压等。所谓规范,就根据接口标准来扩展功能。如下图,要买一个鼠标,只能买USB接口,不能买PS2接口,买PS2接口的鼠标,电脑无法连接,如安卓的手机就能买苹果的充电器。
什么是程序的扩展性?上例中的打电话、发短信、上网三个组件任意组合又可以组合成新的套餐,如果减少超人套餐的功能,可以随意卸下一个组件,这就是程序的扩展性。
Java中的接口与抽象类相似,但与抽象类不同:
- 接口不可以被实例化—只能作为父类。
- 接口里的方法都是抽象方法—设计与实现完全分离,即在子类中必须实现,所以子类称为实现类。
- 实现类可以实现多个接口—子类可以继承多个父类。
- 接口中的属性都是静态常量—接口没有变量属性,只有字段。
上例中,打电话、发短信、上网三个方法可以分别写在三个接口中,这样就可以自由的组成套餐了。
二、创建接口
【格式】
public interface 接口名{
方法(所有方法都默认为抽象方法,不需要用abstract关键字修饰)
}
【例2.1-01】编程实现USB接口
1、创建接口
2、实现接口—编写实现类(子类)
子类 implements 接口,……
多个接口使用“,”分隔 
3、测试
三、面向接口编程
【例3.1-01】开发打印机
(1)墨盒:彩色、黑白。
(2)纸张类型:A4、B5。
(3)墨盒和纸张都不是打印机厂商提供的。
(4)打印机厂商要兼容市场上的墨盒、纸张。
【分析】
墨盒和纸张的规格是一种规范,打印机需要遵守这些规范:
(1) 制定墨盒、纸张的约定或标准。
(2)打印机厂商使用墨盒、纸张的标准开发打印机。
(3)其他厂商按照墨盒、纸张的标准生产墨盒、纸张。
【编程】
(1) 制定墨盒、纸张的约定或标准

(2)打印机厂商使用墨盒、纸张的标准开发打印机
(3)其他厂商按照墨盒、纸张的标准生产墨盒、纸张



测试
【例3.1-02】接上面引例,办一张移动卡,根据提供的场景进行消费。

1、编写父类
2、编写实子类
话唠套餐子类:
网虫套餐子类
超人套餐子类
3、编写电话卡类

4、编写接口
通话服务接口
短信服务接口
上网服务接口
5、给套餐子类添加接口


6、计费实现方法
计费方法:先从套餐余额中扣除,如果套餐余额不足,按下表从电话卡余额扣除。
套餐计费方法,以超人套餐为例:
(1)通话:call(int time,MobileCard card),time为本次通话时长,card电话卡。
如果套餐通话时长 - 电话卡实际通话时长 >= 1,电话卡实际通话时长+1。否则,
如果电话卡余额>=0.2,电话卡实际通话时长+1,电话卡实际消费金额+0.2,电话卡余额-0.2。
(2)短信:send(int count,MobileCard card),count为本次发短信的条数,card电话卡。
如果套餐短信条数 - 电话卡实际发短信条数 >= 1,电话卡实际发短信条数+1。否则,
如果电话卡余额>=0.1,电话卡实际发短信条数+1,电话卡实际消费金额+0.1,电话卡余额-0.1。
(3)上网:net(int flow,MobileCard card),flow为本次上网使用的流量,card电话卡。
如果套餐流量 - 电话卡实际使用流量 >= 1,电话卡实际使用流量+1。否则,
如果电话卡余额>=1,电话卡实际使用流量+1,电话卡实际消费金额+1,电话卡余额-1。
以超人套餐为例:

模拟场景
(1)过年群发祝福短信100条。
编写电话卡MobileCard类的send(int count)方法
实现场景
(2)与女朋友通话30分钟。(略)
(3)打游戏用了100G流量。(略)
四、instanceof运算符
当对象实现了多个接口,在调用对象从接口继承来的方法时,需要将对象强制转换为接口类型。为了避免类型转换异常,在强制类型转换之前通过instanceof运算符检查对象的真实类型。
对象 instanceof 类或接口,结果为true或false
【练习】
1、用接口实现:
2、顾客去市场组装一台电脑,打印出电脑配置。
(1)电脑硬盘和内存可以选择不现厂商的产品。
(2)硬盘可以更换为500G或300G。
(3)内存可以更换为8G或16G。
3、生成厂家生产三类门,一类是防盗门(SecurityDoor),具有开门、关门、加密、解密的功能,一类是普通门(OrdinaryDoor),具有开门、关门的功能,一类是防弹门(ShellproofDoor),具有开门、关门、加密、解密、防弹的功能。为了提高生产效率,厂家创建三块门的模板,用模板进行门的生产。
(1)门模板(Door):具有开门(open)、关门(close)功能
(2)锁模板(Lock):具有加密(encryption)、解密(decrypt)功能
(3)防弹模板(Shellproof):具有防弹(bulletproof)功能
请编写一个程序,生成普通门、防盗门和防弹门。
