感悟:要想成为合格工程师,必须拥有面向对象思维
初级工程师和高级工程师以及架构师最大的区别就是等级越高看问题的角度就不一样,犹如初级工程师写系统完全就是面向过程 if else写满整个类,而且类之间的耦合性很大,不好维护,牵一发而动全身,扩展性很不好。他们站在角度就是能完成功能需求,但是高级工程师以及架构师站在项目角度,考虑未来需求变化和如何做到可维护性、可复用、可扩展(当然这里从代码层面,还有就是从系统架构层面考虑后面单设栏目进行分析)。
将独立模块(可能是独个方法或多个类,甚至一个系统)逻辑封装起来,便于复用,维护。
尽量让依赖方知道的越少越好,将复杂逻辑封装在一个类中的方法中或模块中。 例如根据需要传入对应的参数,然后获取相应的结果,获取结果过程我们并不care,我只想要结果是什么,复杂的逻辑封装起来就好。
将公共逻辑(包括属性、方法)放在一个父类中,然后不同的子类继承父类重写其方法,因此有不同的表现。依赖方只需要拿到抽象父类,并不需要知道具体实现类,降低模块之间的耦合性。
出现父类的地方一定可以被其他子类替换掉,这个就是后面讲到的面向对象四大设计原则中的里氏替换原则
编译时多态:方法的重载 方法签名(方法名+方法参数类型+方法参数个数,返回类型不能唯一区分方法)
运行时多态:在运行的过程中,jvm才知道抽类的引用具体指向那个子类对象,当调用抽象类的方法时实际上调用的是该子类中的方法
java中的类型:类、接口、数组、基本类型 四种类型,前三种属于引用类型,可以实例化对象
类组成:属性(类型(java中的类型) 属性名)、方法(行为 返回类型 方法名(类型 参数名…))、内部类
例如 游泳这个方法,A人和B人是不同对象 A的体力(类的属性值)好 B的体力弱些 那么游泳这个行为表现就不一样,A比B游的远
编程和生活结合:
1、利用面向对象思想设计系统步骤:
在编程中我们要实现一个系统或完成某个功能首先应该考虑由那些模块组成和关系,然后从中抽出公共模块。
而设计具体的某个模块的实现时应该考虑需要那些类和类与类之间的关系以及类的属性和方法,例如A类某中行为需要依赖B类来完成,这个时候A类中的属性具有B类。为了降低耦合和便于扩展这里依赖的是一个抽象类或接口。
上面的类只是一个概念,要想完成一个功能必须要以上面设计的类为模版创建对象来实现。当然对于一个static 属性和方法除外因为这个属性和方法是类独有的(也就是所有该类对象共享)
需要完成一个这样一个功能: 修改数据库用户id=8 name=“haha”,这个时候需要有个User类 属性 id name有get set方法,还有一个UserDAO类有个updateUser(User user)更新user表数据的方法,这个步骤就是设计类, 第二步就是创建id=8 name="haha"User对象,然后还创建UserDAO对象,将User对象传入updateUser方法中,这样就完成了更新用户id=8名字这么个需求。
2、生活中的面向对象
在我们生态系统中,我眼前的都可以看作是对象,Thinking in java中说到Every thing is object一点都没说,人类的衣食住行,等等生活就可以看作成对象,从前面讲到一个对象必须要有一个类模版,所以更抽象一步我们需要知道有那些类。
例如:你、他、我都是对象由人"类"创造而成的,人类家离上班地方很远,需要乘交通工具上班,这个时候人类去上班这个行为需要依赖交通工具类(具体对象可以是地铁、汽车、自行车等)依赖抽象类好处更容易扩展。 人类由手类组成的(将手类看作人类的属性),头发类等其他类组成,当构建一个人类对象时需要传入对应的依赖和关联的对象(地铁对象、手对象、头发对象),最后这个人对象就可以完成人类具有的动作了,哈哈?这就是你,不一样的灯火 human!
一个类确保只有一个原因来引起它变化,如果多于一个原因的话就说明该类承担多于一个职责,应考虑进行拆分。单一职责可以保证易于维护,便于扩展和复用,降低耦合性。
例如:设计一个计算器功能,然后A类中具有界面逻辑和计算逻辑,这个明显有两个原因引起A类变化,如果界面逻辑改变需要改动A类,如果计算逻辑改动了也要改动A类,明显就不符合单一职责原则,因此就需要将界面逻辑和计算逻辑拆分成两个类,这样计算逻辑也很容易被复用。
对(类、模块、方法)修改封闭,但是扩展是开放的。 类或模块依赖的是抽象,当需要增加一种具体实现只需要从抽象中扩展,无需更改原来的类,这个就需要在继承、多态、接口基础上来实现的。
计算机系统内部也引用了面向对象思想:将 内存、cpu、主板、磁盘可以看作成类,他们之间都是根据对应的接口进行设计的(例如内存需要使用主板某个方法,此时需要依赖抽象的主板的方法) 假如内存使用了具体某个品牌的主板,如果内存坏了,替换内存就会导致替换主板的尴尬。
单一职责原则:例如内存坏了就换内存,不应该成为替换cpu的原因
开闭原则:例如内存不够了,在主板上有足够的插槽时可以添加内存条,如果磁盘不够时可以通过pc usb接口接上添加移动硬盘
1、高层模块不应该依赖底层模块,高层和底层模块都要依赖抽象类(接口)
例如 内存、cpu都依赖于具体的主板,如果主板一坏导致cpu、内存都不可用,这是不合理的,高层模块依赖底层模块会导致高层模块复用性很差,如果都依赖抽象的话,高层和底层都可以复用
2、抽象不依赖细节,细节依赖抽象
也就是面向接口进行编程,不需要care具体的实现,只需调用对方提供的接口,传入相应参数获取对应的值
父类的抽象方法子类需要实现,但是已经实现的方法,子类不应该重写。 也就是父类出现的地方可以使用其他子类对象进行替换,这也是实现多态,开闭原则的基础。
迪米特法则也称最少知识原则,用于降低类之间的耦合度。如果A类和C类没有必要进行彼此通讯,如果A类调用C类方法m1,可以通过第三者转发调用。这样就大大提高了代码复用,如果想要修改C类的m1那么之前如果A类、B类直接引用C类调用方法m1,那么导致都需要进行该动,现在如果通过第三者进行转发,只需要改动第三者就行,A、B类无需更改。
还有一个好处就是,第三者可以控制将这次的调用委派给那个类,灵活性更高。