面向对象分析、设计
分析和设计就是字面意思,类似于需求分析、系统设计。不同之处在于”面向对象“是对类或对象的设计,将需求拆解为类中包含哪些方法、类之间有什么关系,更加贴合代码实现,更容易落地。
面向对象编程
面向对象编程是一种编程范式或编程风格。以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石。
后面会展开介绍面向对象编程的四大特性。
补充说明:面向对象编程如果接在分析、设计之后是一个动作,是实际编码落地的动作,更多的时候面向对象编程说的是一种编程风格。
封装
首先介绍一下什么是封装?封装也叫做信息隐藏或者数据访问保护,类通过暴露有限的访问接口,授权外部仅能通过类提供的方法来访问内部信息或者数据。
👆🏻上面的概念看不懂没关系,大白话举例讲一下:你有很多稀有书,但是不想让其他人随便去看,规定只能通过向你借才能看到书的内容。既你本人是对其他人看你的书有限制的,只能通过你规定的途径才可以看到书。
下面用代码举例
public class Person {
private long lastBorrowTime;
private List<Book> bookList;
/**
* 向我借书
*/
public List<Book> borrowBooks() {
this.lastBorrowTime = System.currentTimeMills();
return bookList;
}
public long getLastBorrowTime() {
return lastBorrowTime;
}
}
从上述代码可以看到只有调用borrowBooks()方法才能从我这里看到这些书,直接去访问Person.bookList是看不到的。
在上述代码中对于bookList这个参数是用private去修饰的,而borrowBooks()方法是用public去修饰的,对于封装这个特性,需要编程语言本身支持一种语法:访问权限控制
封装可以解决哪些问题?
封装限制了对类中属性的访问,如果不设限制可以随意访问、修改类中的属性,这样用起来十分灵活,但灵活的同时也会带来一些问题,例如:
- 不通过方法去借书,直接访问bookList参数,导致lastBorrowTime没用更新
灵活的代价就是调用者需要对业务细节十分了解,对调用者而言也是极大地负担,反之将属性封装起来给调用者,调用者不需要过多的取了解业务细节,还可以减少出错的几率。
总结下封装主要就是隐藏信息,保护数据。
抽象
抽象是为了隐藏方法的实现,让调用者只需要关心有哪些方法,方法的入参和返回值是什么,其中具体的实现不需要去关心。
因为抽象是非常通用的一个设计思想,而且不需要编程语言有特殊的语法去支持,抽象有时候会被排除在面向对象的特性之外。
抽象用来解决哪些问题?
抽象是一种只关注功能点,不关注实现细节的设计思路,可以帮我们过滤掉非关键性的实现细节,帮助复杂系统的拆解设计。
继承
继承用来表示类之间的A is a B 关系,例如:狗是动物。
继承用来解决哪些问题?
继承最大的一个好处就是解决代码复用的问题,子类继承父类,可以继承父类中的代码,多个子类相同的代码可以抽到父类中,减少代码冗余的情况。
但是, 如果继承层级过深、过复杂会导致代码可读性、可维护性降低,想要了解一个子类需要按照继承关系一层一层的寻找父类才能真的了解子类。
多态
多态是指子类可以替代父类,在实际代码运行的过程中执行子类的方法。 通俗的来讲,就是同一个接口,不同的实例执行会产生不同的结果(个人理解)
其中编程语言存在多态的三个前提条件:
- 继承
- 重写
- 父类引用指向子类对象 Animal animal = new Dog();
多态用来解决哪些问题?
利用多态特性,父类的一个公用接口可以覆盖到所有子类,同样解决了代码复用性的问题,同时子类仍保留对外扩展的能力。
3W模型总结——引用
封装
What:隐藏信息,保护数据访问。
How:暴露有限接口和属性,需要编程语言提供访问控制的语法。
Why:提高代码可维护性、降低接口复杂度、提高类的易用性。
抽象
What:隐藏具体实现,使用者只需要关心功能,无需关系实现。
How:通过接口类或者抽象类实现。
Why:提高代码扩展性、维护性;降低代码复杂度,减少细节负担。
继承
What:表示 is-a 关系,分为单继承和多继承。
How:需要编程语言特殊语法支持,例如 Java 的 extends。
Why:解决代码复用问题。
多态
What:子类替代父类,在运行时调用子类的实现。
How:需要编程语言特殊语法支持,比如继承、接口类、duck-typing。
Why:提高代码扩展性和复用性。