面向对象
- 面向对象编程(OOP - Object Oriented Programing)
面向过程与面向对象的区别
- 面向过程与面向对象都是我们编程中编写程序的一种思维方式.
- 面向过程的程序设计方式,是遇到一件事时.思考"我该怎么做",然后一步步实现的过程.
- 面向对象的程序设计方式,是遇到一件事时,思考"我该让谁来做",然后那个"谁"就是对象.
使用面向对象的好处
- 面向对象思维方式是一种更加符合人类思考习惯的思想
- 面向对象中更多体现的是指挥(指挥对象做事情)
- 面向对象思维方式将复杂的问题简单化
面向对象举例
- 超市
- 客户
- 姓名:小龙女
- 身高:165cm
- 体重:45kg
- 操作:购物
- 收银员
- 姓名:杨过
- 部门:财务部
- 员工编号:0001
- 操作:收银,打印账单,刷卡
public class MIanXiang {
String color;
int number;
public void run(){
System.out.println("一辆颜色为"+color+"轮子数为"+number+"的车行驶在蜿蜒的马路上");
}
}
类与对象的区别
- 在程序中对事物的描述与该事物在现实中的形态保持一致.为了做到这一点,面向对象的思想中提出来两个概念,既类和对象.其中,类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体.
面向对象的三大特征
-
封装
- 只隐藏对象的属性和实现细节,仅对外提供公共的访问方式.
- 好处:将变化隔离,便于使用,提高复用性,提高安全性.
- 原则:将不需要对外提供的内容隐藏起来;把属性隐藏,提供公共方法对其访问.
-
继承
- 子类自动拥有父类非私有的属性和方法.
- 提高代码的复用性,继承是多态的前提
-
多态
- 类的多种形态,是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象.
- 前提:实现或继承关系;覆写父类的方法
- 好处:提高了程序的扩展性
- 弊端:当父类引用指向子类对象时,虽然提高了扩展性,但只能访问父类中具备的方法,不可访问子类中的方法:即访问的局限性.
========================================
面向对象设计原则
- 1.开放封闭原则
- 2.接口隔离原则
- 3.组合|聚合原则
- 4.里式替代原则
- 5.最少知识原则(迪米特法则)
- 6.单一职责原则
- 7.依赖倒置原则
开放封闭原则(可以扩展,但不能修改)
- 因为:开放封闭原则主要体现在对扩展开放,对修改封闭,意味着有新的需求或变化时,可以对现有的代码进行扩张,以适用新的情况,软件需求总是变化的,因此对软件设计人员来说,必须在不需要对原有系统进行修改的情况下,实现灵活的系统扩展.
- 所以:可以通过Template Method模式和Strategy模式进行重构,实现对修改封闭,对扩展开放的设计思路。 封装变化,是实现开放封闭原则的重要手段,对于经常发生变化的状态,一般将其封装为一个抽象,拒绝滥用抽象,只将经常变化的部分进行抽象.
接口隔离原则(多个接口优于单一通用接口)
- 因为: 提供尽可能小的单独接口,而不要提供大的总接口。暴露行为让后面的实现类知道的越少越好。
- 所以: 建立单一接口,不要建立庞大的接口,尽量细化接口,接口中的方法尽量少。也就是要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的约定,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
- 从大局来说Java的接口可以实现多继承就是接口隔离原则的基础保障.
组合|聚合复用原则
- 因为:其实整个设计模式就是在讲如何类与类之间的组合/聚合,在一个新的对象里面通过关联关系(包括组合关系和聚合关系)使用一些已有的对象,使之成为新对象的部分,新对象通过委派调用已有对象的方法达到复用其已有功能的目的,也就是说尽量使用类的合成复用,尽量不要使用继承.
- 如果未来复用,便使用继承的方式将两个不相干的类联系在一起违反里氏替换原则,那是生搬硬套,忽略了继承的缺点**,继承复用破坏数据封装性**,将基类的实现细节全部暴露给了派生类,基类的内部细节常常对派生类是透明的,白瞎复用;虽然简单,但不安全,不能在程序的运行过程中随意改变,基类的实现发生了改变,派生类的实现也不得不改变,从基类继承而来的派生类是静态的,不可能在运行时间内发生改变,因此没有足够的灵活性.
- 所以?*组合/聚合复用原则可以使系统更加灵活,类与类之间的耦合度降低,一个类的变化对其他类造成的影响相对较少.**因此,一般首选使用聚合/组合来实现复用,其次才考虑继承,在使用继承时,需要严格遵循里氏替换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用.
里氏替换原则
- 因为: 里氏替换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。里氏替换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
- 所以: 使用里氏替换原则时需要注意,子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法。尽量把父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现。
迪米特法则
- 因为:类与类之间的关系越密切,耦合度也就会越来越大,只有尽量降低类与类之间的耦合度才符合设计模式;对于被依赖的类来说,无论逻辑多复杂都要尽量封装在类的内部,每个对象都会与其他对象有耦合关系,我们称出现成员变量,方法参数,方法返回值中的类为直接的耦合依赖,而出现在局部变量中的类则不是直接耦合依赖,也就是说,不是耦合依赖的类最好不要作为局部变量的形式出现在类的内部.
- 所以: 一个对象对另一个对象知道的越少越好,即一个软件实体应当尽可能少的与其他实体发生相互作用,在一个类里能少用多少其他类就少用多少,尤其是局部变量的依赖类,能省略尽量省略。同时如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一方法的话,可以通过第三者转发这个调用.
单一职责原则
- 对一个类来说,应该仅有一个引起它发生变化的原因.
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;提高类的可读性,提高系统的可维护性;变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则.
依赖倒置原则
- 抽象不应依赖于细节,细节应该依赖于抽象.
-
- 因为: 具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,这个时候,B不应当直接使用A中的具体类;而应当由B定义一个抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口;这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成循环依赖。
- 所以: 采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性和可维护性。
理解:
面向对象六大原则?
单一职责原则(Single-Resposibility Principle)。
开放封闭原则(Open-Closed principle)。
Liskov替换原则(Liskov-Substituion Principle)。
- 子类型必须能够替换掉它们的基类型。本原则和开放封闭原则关系密切,正是子类型的可替换性,才使得使用基类型模块无需修改就可扩充。
依赖倒置原则(Dependecy-Inversion Principle)。
接口隔离原则(Interface-Segregation Principle)。
良性依赖原则。