一、面向对象三大特性
1.封装:对外隐藏类的属性和变量,通过接口(方法)的形式提供给外面,避免外部修改内部数据。封装性就是利用接口将数据和基于数据的操作封装在内部,保护数据并隐蔽具体的细节,只保留有限的接口与外界联系。
public class Student { private String name;// 声明一个私有字符串变量,表示姓名 private int age;// 声明一个私有整型变量,表示年龄public Student(String name, int age, String sex, String major) { // 有参构造方法 this.name = name; this.age = age; } public String getName() { //获得姓名的方法 return name; } public void setName(String name) { //设置姓名的方法 this.name = name; } public int getAge() { //获得年龄的方法 return age; } public void setAge(int age) { //设置年龄的方法 this.age = age; }}
2.继承:使子类的对象拥有父类的全部属性和行为(protect和public),同时可以增添自己的所特有的属性和行为。这样有利于代码的复用,避免重复造轮子,这就是继承的基本思想。
3.多态:简单来说就是一个程序中同名的多个不同方法共存的情况,通常使用方法的重载和重写(也叫覆盖)来实现类的多态性。
重载:方法名一样,参数列表不一样。不同的参数列表可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);
重写:子类重新实现父类的虚方法。
封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用
二、类间的关系
1.继承,对于类来说,这种关系叫做继承,对于接口来说,这种关系叫做实现。
2.依赖,一个类A中的方法使用到了另一个类B。一般而言,依赖关系在Java中体现为局域变量、方法的形参,或者对静态方法的调用。
public class Pen { public void write(){ System.out.println("use pen to write"); }}public class Me { public void write(Pen pen){ //这里,pen作为Me类方法的参数 pen.write(); }}
3.聚合,b类是a类的一部分,一种强引用关系,b类生命周期跟a类没有关系,所以a类删除时,b类不会被删除。一般而言,聚合关系在Java中体现为成员变量。例如界面和数据类的关系,界面被销毁,但是数据类不会被销毁。
4.组合,b类是a类组成的一部分,比聚合更强的引用关系,a类的生命周期结束也就意味着b类的生命周期结束,所以a类删除时,b类一定会跟着删除。一般而言,聚合关系在Java中体现为成员变量。例如界面和他的子界面、item的关系,界面被销毁时,子界面、item都会被销毁。
少用继承,多用组合。
继承的缺点:
1.破坏封装性,有时候需要实现子类不需要的方法,例如
鸭子是不要飞的,那么如果你要解决这个问题,你需要在封装一层
那如果再来一个会游泳的鸟,会下蛋的鸟呢,那你的继承层级可能会多达十种,继承层级一旦多于三层,就较难理解、维护了。但是如果把会游泳、会飞、会下蛋等特性做成功能组件自由组合就不会有这个问题了。
2.紧耦合,修改父类可能会影响所有的子类以及子类的调用类,例如修改方法签名(返回值、名字、参数列表),会影响到所有子类。
三、设计模式六大原则
1.职责单一:一个类只负责一项职责,如果这项职责很复杂,可以拆分成多个子功能进行组合,避免一个类过于庞大,难以修改。
问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。
2.依赖倒置:实现依赖抽象,高层模块不应该依赖低层模块,二者都应该依赖其抽象。使用接口、抽象类的方法,参数使用接口(抽象)类进行传递,便于不同子类的传参。
问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
3.里氏替换:所有父类出现的地方都能用子类代替,子类不应该修改父类已经实现的方法。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
问题由来:有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。
4.接口隔离:设计接口尽量精简,客户端不应该依赖它不需要的接口。
问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。
5.迪米特原则(最少知道):一个类对自己依赖的类知道的越少越好。尽量降低类与类之间的耦合,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。
问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
6.开闭原则:对修改关闭,对扩展开放。