//来自极客时间的学习笔记
接口和抽象是面向对象的两个基本机制
接口
接口是对行为的抽象,是抽象方法的集合,利用接口可以达到 API 定义和实现分离的目的,并且不能实例化。
抽象
抽象类是不能实例化的类,用关键字 abstract
修饰,主要目的是复用代码。除了不能实例化,形式上和一般的 Java
类并没有太大区别,可以有一个或者多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关 Java
类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。Java
标准库中,比如 collection
框架,很多通用部分就被抽取成为抽象类,例如 java.util.AbstractList
。
举个栗子
Java 类实现 interface
使用 implements
关键词,继承 abstract class
则是使用 extends
关键词,我们可以参考 Java
标准库中的 ArrayList
。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//...
}
深入了解这个问题的几个作用
- 掌握 Java 语言特性演进。现在非常多的框架已经是基于 Java 8,并逐渐支持更新版本,掌握相关语法,理解设计目的是很有必要。
- 至少要知道经典的使用场景,掌握类库设计的基本使用,掌握设计方法,能在 review 代码的时候发现不利于未来维护的设计。
- 对于 Java 的基本元素的语法是否理解准确。
面向对象基础
封装
封装的目的是隐藏事务内部实现的细节,以提高安全性和简化编程。提供合理的边界,避免外部调用者接触内部的细节。我们在日常开发中,因为无意间暴露了细节导致的难缠 bug 太多了,比如在多线程环境暴露内部状态,导致的并发修改问题。
继承
代码复用的一种基础机制。但要注意,继承可以看作是非常紧耦合的一种关系,父类代码修改,
父类代码修改,子类行为也会变动。在实践中,过度滥用继承,可能
会起到反效果。
多态
你可能立即会想到重写(override)和重载(overload)、向上转型。简单说,重写是父子类中相同名字和参数的方法,不同的实现;重载则是相同名字的方法,但是不同的的参数,本质上这些方法签名是不一样的。
S.O.L.I.D
单一职责(Single Responsibility)
类和对象最好只有一种职责
开关原则(Open-Close, Open for extension, , close for modification)
设计要对扩展开放,对修改关闭。换句话说,程序设计应保证平滑的扩展性,尽量避免因为新增同类功能而修改已有实现,这样可以少产出些回归(regression)问题。
里氏替换(Liskov Substitution)
进行继承关系抽象时,凡是可以用父类或者基类的地方,都可以用子类替换。
接口分离(Interface Segregation)
我们在进行类和接口设计时,如果在一个接口里定义了太多方法,其子类很可能面临两难,就是只有部分方法对它是有意义的,这就破坏这就破坏了程序的内聚性。
依赖反转(Dependency Inversion)
实体应该依赖于抽象而不是实现。也就是说高层次模块,不应该依赖于低层次模块,而是应该基于抽象。实践这一原则是保证产品代码之间适当耦合度的法宝。
代码实践
public class VIPCenter {
void serviceVIP(T extend User user>) {
if (user instanceof SlumDogVIP) {
// 穷 X VIP,活动抢的那种
// do somthing
} else if(user instanceof RealVIP) {
// do somthing
}
// ...
}
修改后:
public class VIPCenter {
private Map<User.TYPE, ServiceProvider> providers;
void serviceVIP(T extend User user) {
providers.get(user.getType()).service(user);
}
}
interface ServiceProvider{
void service(T extend User user) ;
}
class SlumDogVIPServiceProvider implements ServiceProvider{
void service(T extend User user){
// do somthing
}
}
class RealVIPServiceProvider implements ServiceProvider{
void service(T extend User user) {
// do something
}
}