OOAD:面向对象的分析和设计
1.什么是面向对象
面向对象(Object-Orientation,简称OO)是一种系统建模技术/编程思想。
面向对象编程(Object-Orientation Propramming,简称OOP)是按照OO的方法学来开发程序的编程方式。
面向对象分析方法 Object-Oriented Analysis, 简称OOA
分析阶段主要解决以下问题:
1.建立针对业务问题域的清晰视图
2.列出系统必须要完成的核心任务
3.针对问题域建立公共词汇表
4.列出针对此问题域的最佳解决方案
此阶段要解决的核心问题是"what to do?
面向对象设计 Object-Oriented Design, 简称OOD
设计阶段主要解决以下问题:
1.如何解决具体的业务问题
2.引入系统工作所需的各方面的支持元素
3.定义系统的实现策略
此阶段要解决的核心问题是"How to do?"
OO: 面向对象,是一套集编程思想,方法,原则,模式,解决方案等为一体的编程模式。OO的思想贯穿于整个软件开发的过程,比如需求分析,设计,编程,测试,升级等.
2.OO(面向对象)的特点
1.抽象:忽略掉一个对象或实体的细节而只关注其本质特征的过程。
2.封装:
目的:实现信息的隐藏
1.属性信息
2.行为的操作的信息
隐藏方法实现的细节。
代码重用。
3.继承:
is a
1.子类可以继承父类的属性、方法
2.子类可以有自己的特性存在。
4.多态:相同类域的不同对象调用相同方法时的不同表现形式
Person p1 = new Student();
Person p2 = new Teacher();
p1.work();//听课
p2.work();//讲课
1.子类继承父类,类实现接口
2.子类重写父类的同名方法,类实现接口中的抽象方法
3.父类的引用指向子类的对象,接口类型的引用指向具体实现类的对象
重写/重载
运行时多态:重写
编译时多态:重载
3.OOP(面向对象编程)
类:属性 方法
抽象 实例化
事物--------------->类-------------->内存中的对象
对象分为
域对象:在整个对象的设计过程中,侧重于做数据的封装/传递。用来做数据处理的类,信息的载体。POJO,JavaBean.
行为对象:侧重于行为的操作,逻辑的实现。此类对象常见于接口的实现类,抽象类的扩展类.
类(对象)之间的关系:
继承关系:is a
依赖关系:类A对象中并不需要存在有类B类型的对象属性,而是在使用时,直接在方法中实例化类B(new对象)来调用相关的业务方法来完成整个业务操作。
use a
关联关系:对象之间交互时的一种引用方式,当一个对象通过另外一个对象的引用(成员变量)去使用另外一个对象的服务或操作时,两个对象时间便产生了关联。
关联关系又可总体分为聚合关系和组合关系:
聚合关系和组合关系的特点及其区别:
1.聚合关系也称"has-a"关系,组合关系也称"contains-a"关系
聚合(Aggregation): ---Has a---------人拥有电脑
组合(Composition): ---Contains a---人是由脚、身体、头等部分组成的
2.聚合关系表示事物的整体/部分关系的较弱情况,组合关系表示事物的整体/部分关系的较强的情况.
3.在聚合关系中,代表部分事物的可以属于多个聚合对象,可以为多个聚合对象共享,而且可以随时改变它所从属的聚合对象.代表部分事物的对象与代表聚合事物对象的生存期无关,一旦删除了它的一个聚合对象,不一定也就随即删除代表部分事物的对象.在组合关系中,代表整体事物的对象负责创建和删除代表部分事物的对象,代表部分事物只属于一个组合对象.一旦删除了组合对象,也就随即删除了相应的代表部分事物的对象.
OOP的过程中核心原则:
1.尽量能使用封装的特性就是用封装
2.面向接口编程。
3.重组合/聚合而轻继承
4.抽象类和接口的选择问题
1.语法角度:
Interface:
属性:public static final
方法:只能是抽象方法
注意:可以没有任何方法
被实现类实现。
Class:abstract来修饰的。
属性:正常属性
方法:可以是普通方法,
可以是抽象方法。
注意:可以没有任何抽象方法
被子类继承。
2.设计角度:
一个类可以实现多个接口但是一个类只能继承一个父类。
接口和抽象类的设计,都是在有意识的规避java不能多继承的操作
接口是抽象类的极致的抽象。
3.思想角度:
1.类进行抽象的时候是否关注属性
2.尽量让问题域独立存在,跟据操作选择合适的抽象类或接口.
例如:一个关于门的设计问题
门都有俩个基本的行为 open close
将来系统中会出现很多种门(不同的类)
MyDoor1 MyDoor2 MyDoor3 MyDoor4
这些类都具备open close的行为,但是具体实现又不一样.
如何选择:
1.抽象出一个抽象类,类中俩个抽象方法open close alarm
2.抽象出一个接口,接口中俩个抽象方法open close
将来多了一个新的功能:警报器
1.抽象出一个抽象类,类中俩个抽象方法open close
MyDoor1 extends Door
2.抽象出一个接口,接口中俩个抽象方法alarm
5.设计模式的定义与作用
定义:
对软件设计问题的可重用的解决方案.
作用:
1.重用设计比重用代码更有意义,可充分利用已有的软件开发经验.
2.为设计提供共同的词汇,方便交流和书写开发文档.
3.降低错误可能性.
4.节省时间.
好的软件系统设计至少应该具备以下三点:
可扩展性(Extensibility)
灵活性(Flexibility)
可插入性(Pluggability)
面向对象设计原则:
常用基本的设计原则有七个:
单一职责原则(Single Responsibility Principle,SRP)
类的职责要单一,不能将太多职责放在同一个类中.
开闭原则(Open-Closed Principle, OCP)
对扩展开放,对修改关闭。软件设计应该尽可能的使架构稳定而且又容易满足不同的需求,提高代码可重用性。理论上希望能达到不修改源代码的前提下扩展功能。
里氏代换原则(Liskov Substitution Principle,LSP)
在系统中,一个可以接受基类对象的地方必然可以接受一个子类对象。
依赖倒转原则(Dependency Inversion Principle,DIP)
要针对抽象编程,而不是针对具体类编程.
接口隔离原则(Interface Segregation Principle,ISP)
使用多个专门的接口来取代一个统一的接口.
合成复用原则((Composition/Aggregate Reuse Principle,CARP)
系统中尽量使用组合和聚合的关系,而尽量少用甚至不用继承关系。
迪米特法则(Law of Demeter, LoD)
一个软件实体应当尽量少的与其他实体发生相互作用.
又叫做最少知道原则。也就是说一个对象应当对其他对象要尽可能少的了解,不要和陌生人说话。
在面向对象中的基本设计原则基础上,又出现了各种各样的设计模式.
面向对象设计模式:
GRASP模式:
General Responsibility Assignment Software Patterns,通用责任分配软件模式
GOF模式:
Gang Of Four,"四人帮"设计模式:
Erich Gamma, Richard Helm, Ralph Johnson,John Vlissides软件设计领域的四位世界顶级大师.合著有《设计模式:可复用面向对象软件的基础》,提出了23种基本设计模式,从理论高度提炼并规范了设计模式,对面向对象设计,软件复用领域产生了巨大影响。
6. GRASP模式(通用责任分配软件模式)
什么是责任:
类要完成一定的功能,那么就需要具备一定的责任,也可以将责任理解成一个业务功能
我们可以把责任分为俩种:
知道责任——表示知道要处理的数据是哪些
行为责任——表示知道怎么处理已知的数据
责任=知道责任+行为责任
知道责任:
了解私有封装数据
了解关联的对象
了解能够派生或计算的事物
行为责任:
完成对象初始化
执行一些控制行为
面向对象设计过程就是将责任分配给对象的过程
例如:
在一个销售业务中,客户有交费的功能,可将它识别为一个责任。
我们在写一个类Payment来完成这个功能的时候,其实就是在完成责任分配的过程。
1.Payment类的对象需要知道交费过程中所需的各种数据
2.Payment类的对象需要拥有处理这些数据的方法
7. GRASP模式的分类
作用/则重点:完成责任分配
GRASP模式也是遵循基本的设计原则的(也就是说GRASP模式是在基本设计原则基础之上建立的).
Information Expert(信息专家)
谁能够在某方面具有完整的信息,足以实现某个责任,就将责任分配给这个类,这个类即所谓的信息专家。
总结为"谁知道谁负责"
1.要知道的责成内容是什么
2.完成这个责任需要哪些信息
3.哪些对象拥有这些完成的信息
4.分配责任的同时不能违反基本的设计原则
例如:在购物车系统中,要让每个商品(Item)在购物车(ShoppingCar)中只出现一次,如果放相同的商品到车上就只更新该商品的数量而不增加商品项
Creator(创造者)
A是B的容器或者A和B是聚合关系
A有初始化B所需的信息
A需要记录/使用B的实例
具有以上特性,可让A具有创建/创造B类对象的责任
例如:我们使用过的工厂类ConnectionFactory/SessionFactory以及spring中的容器都是这个遵循这种责任配置模式下的产物.
Low Coupling(低耦合)
减少类间的耦合(关联/依赖等等),使一个类的修改对其它类的影响范围有所降低,从而系统变得更容易维护
使得系统变得更容易理解
总结为"不要和陌生人说话"
High Cohesion (高内聚)
提高类的通用性,并控制类的复杂程度,努力分解类使得类具有独立的责任.
优点:
高内聚可表现关联责任的一个抽象,易于实现类的重用
高内聚使维护工作变得简单
高内聚使得系统模块化工作,方便团队工作
例如:
非常低的内聚:一个类单独处理很多不同模块的事务。比如它既处理对数据库的存取,又处理用户接口图形处理。
比较低的内聚:一个类单独处理一个模块内的所有事务。
高内聚:类只处理与模块相关的功能,一个类具有一个相对独立的责任,且与其它类合作共同完成任务。
Controller (控制器)
能全面代表系统或子系统的类,比如系统事件的接收和处理通常由一个高级类来代替,称为控制器类.
不要试图只定义一个控制器类,那样会违反高内聚的原则,一个子系统会有多个控制器类,分别处理不同的事情.
控制器不是用户界面类,但通常与界面类关联(MVC模式).
Polymorphism (多态)
在OOP看来,提供了静态多态和动态多态,前者包括函数重载和模板两种形式,都是在编译期根据参数类型检查来确定调用哪个函数或使用哪个具体参数类型;后者运行时即时编译根据内存和虚函数表查找确定调用哪个函数.
多态,尤其是动态多态性使得系统具有不变应万变的特性.
Pure Fabrication (纯虚构)
和多态性是同一概念,虚构顶层基类针对抽象编程。
纯虚构就是要虚构一个基类,将对象尽量组织成继承树的形式,客户端代码只引用了基类的形式。
例如:
设计一个绘图类,要求能在不同的系统如Linux以及Windows下绘画,如何满足?设计一个高层次的抽象类,用于分配这个职责。
Indirection (间接)
增加一个中介类,用于避免两个类直接耦合。
在实体世界向关系世界的转化中,对多对多的关系需要增加一个实体转换为两个一对多关系。
例如:
n n
Employee-----------Position
n 1 1 n
Employee-----------Assignment-------------Position
员工类 分配类 岗位类
(这是个中介类)
一个员工对于一个分配方式
一个分配方法对于一个岗位
分配类将员工类和岗位类间的多对多关系转换为两个1对多的关系