四大特性
封装抽象继承多态 面向对象与面向过程比较
面向过程的特性面向对象的相对优势日常开发中一些面向过程开发风格的问题
滥用getter、setterConstants、Utils类的设计问题基于贫血模型的开发模式 接口与抽象类
接口抽象类基于接口而非实现编程 组合与继承需求分析
划分职责进而识别出有哪些类定义类及其属性和方法定义类与类之间的交互关系将类组装起来并提供执行入口
【学习、总结极客时间的专栏《设计模式之美》之后的个人总结】
面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。
四大特性 封装封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式(或者叫函数)来访问内部信息或者数据。对Java语言,通过访问控制权限,来限定对类中成员变量的访问,如private、public等关键字,来限定对类对象的访问。
封装的意义在于,需要对类中的成员变量访问做控制,避免任何代码都可以访问、修改类的属性,从而影响代码可读性、可维护性;同时,只暴露必要的方法给调用者使用,能够降低调用者的使用难度,比如一个机器,只有几个按钮,比有几十个按钮,更适合一般情况下的使用。
抽象抽象讲的是如何隐藏方法的具体实现,让调用者只需要关心方法提供了哪些功能,并不需要知道这些功能是如何实现的。在java中,是通过接口类(interface关键字定义的类)或抽象类(abstract关键字定义的类)来实现抽象。
抽象是一个通用的设计思想,是只关心功能、不关心实现,从而可以过滤掉很多繁杂的信息、去干其它重要的开发工作;很多设计原则都体现了抽象这种设计思想,比如基于接口而非实现编程、开闭原则(对扩展开放、对修改关闭)、代码解耦(降低代码的耦合性)等。
注意点有:不要在方法名、类名定义中,暴露太多实现细节。比如获取一个图片地址,可以写成getPictureUrl(),但是写成getTencentPictureUrl(),就暴露了具体实现。
继承继承是指类之间的is-a关系,java语言只支持单继承,即单个父子关系。继承最大的一个好处就是代码复用。假如两个类有一些相同的属性和方法,我们就可以将这些相同的部分,抽取到父类中,让两个子类继承父类。这样,两个子类就可以重用父类中的代码,避免代码重复写多遍。
但是过度使用继承,会导致代码层数过深、嵌套过多,降低代码的可读性、可维护性。这一点可以通过“多用组合少用继承”的方式来解决。
多态多态是指,子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。多态也是能够用于提升代码的复用性,是很多设计模式、设计原则、编程技巧的代码实现基础。在java语言中,多态是通过子类继承抽象类、普通类,或者子类实现接口的方式来起作用的。
面向对象与面向过程比较 面向过程的特性面向过程编程也是一种编程范式或编程风格。它以过程(可以理解为方法、函数、操作)作为组织代码的基本单元,以数据(可以理解为成员变量、属性)与方法相分离为最主要的特点。面向过程风格是一种流程化的编程风格,通过拼接一组顺序执行的方法来操作数据完成一项功能。
面向过程编程语言首先是一种编程语言。它最大的特点是不支持类和对象两个语法概念,不支持丰富的面向对象编程特性(比如继承、多态、封装),仅支持面向过程编程。
面向对象的相对优势对于大规模复杂程序的开发,程序的处理流程并非单一的一条主线,而是错综复杂的网状结构。面向对象编程比起面向过程编程,更能应对这种复杂类型的程序开发。
面向对象编程相比面向过程编程,具有更加丰富的特性(封装、抽象、继承、多态)。利用这些特性编写出来的代码,更加易扩展、易复用、易维护。
从编程语言跟机器打交道的方式的演进规律中,我们可以总结出:面向对象编程语言比起面向过程编程语言,更加人性化、更加高级、更加智能。
日常开发中一些面向过程开发风格的问题 滥用getter、setter在定义一个对象时,需要考虑是否每个成员变量都需要配置外部访问权限。不控制会导致任何代码都能访问数据,使得面向对象变成了面向过程编程。
Constants、Utils类的设计问题不能设计大而全的类。
基于贫血模型的开发模式将数据与操作分离,将面向对象编程变成了面向过程编程。
接口与抽象类接口与抽象类都不允许被实例化,只能被实现或继承。在java中,它们的区别有这几点:
接口接口不能包含属性接口只能声明方法,不能包含方法实现类实现接口时,必需实现接口中声明的所有方法侧重于解耦,即约定与实现分离,调用者只关心抽象的接口提供的功能,不需要关注具体实现。 抽象类
抽象类可以包含属性和方法,方法既可以包含代码实现,也可以不包含代码实现,不包含代码实现的方法叫做抽象方法。子类继承抽象类,必需重写抽象类的所有抽象方法。能够解决代码复用问题 基于接口而非实现编程
基于接口是指要基于抽象来思考,让接口提供一个通用的功能给调用方。我们在做软件开发的时候,一定要有抽象意识、封装意识、接口意识。越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性、扩展性、可维护性。
在定义接口的时候,不要暴露任何实现细节。接口的定义只表明做什么,而不是怎么做,名称的定义一定要考虑到通用而不是具体实现。而且,在设计接口的时候,我们要多思考一下,这样的接口设计是否足够通用,是否能够做到在替换具体的接口实现的时候,不需要任何接口定义的改动。
组合与继承在继承层数过深时,会出现代码难以维护、可读性变差等问题,可以通过组合来解决这个问题。具体地讲就是通过组合+接口+委托的方式来实现。
继承适合用于层次浅的场景,继承关系不复杂,容易维护;而组合适合在继承层次深、复杂的情况下替代继承。但是组合是对类进行更细粒度的拆分,增加代码的复杂程度和维护程度,更适合于扩展性要求高的情况。
一些设计模式会固定使用继承或者组合。比如,装饰者模式(decorator pattern)、策略模式(strategy pattern)、组合模式(composite pattern)等都使用了组合关系,而模板模式(template pattern)使用了继承关系。
需求分析 划分职责进而识别出有哪些类根据需求描述,把其中涉及的功能点,一个一个罗列出来,然后再去看哪些功能点职责相近,操作同样的属性,是否应该归为同一个类。
定义类及其属性和方法从功能点中挖掘类应该有的属性和方法,要控制对数据的访问
定义类与类之间的交互关系类之间的关系主要有泛化、实现、组合、依赖。
将类组装起来并提供执行入口把各个功能的类进行编排,提供一个统一的入口供外部调用



