一、概述
类图
类与类图
- 类:类名、属性、方法
- 属性写法:
可见性 名称:类型 [ = 默认值]
- 方法写法:
可见性 名称(参数列表) [:返回值类型]
- 可见性
+
:public#
:protected-
:private*
:package
类之间的关系
关联关系
关联关系是一种结构化关系,用于表示一类对象和另一类对象之间有联系。
通常将一个类的对象作为另一个类的属性。
双向关联
默认情况下,关联是双向的。
用不带箭头的实线表示。
单向关联
用带箭头的实线表示,如:顾客has地址,顾客—->地址
自关联
类的属性对象为类本身。
用指向自身的带箭头实线表示。
多重性关联
直接在关联直线上增加一个数字表示与之对应的另一个类的对象个数。
聚合关系
表示一个整体与部分的关系。
成员对象可以脱离整体对象独立存在。
用带空心菱形的直线表示。
组合关系
表示整体和部分的关系。
部分和整体具有统一的生命周期。整体创建,部分创建;整体销毁,部分销毁。
用带实心菱形的直线表示。
依赖关系
某个类的方法使用另一个类的对象作为参数。
由依赖的一方指向被依赖的乙方。
用带箭头的虚线表示。
泛化关系
泛化关系也就是继承关系。
用带空心三角形的直线表示。
接口与实现关系
接口之间也可以由类之间关系类似的继承关系和依赖关系。
接口和类之间还存在一种实现关系。
实现关系用带空心三角形的虚线表示。
面向对象的设计原则:
定义,含义等,不止要知道名字。
设计原则名称 | 设计原则简介 | 重要性 |
---|---|---|
单一职责原则 | 类的职责要单一,不能将太多的职责放在同一个类中。 | ※※※※ |
开闭原则 | 软件实体对扩展是开放的,但对修改时关闭的,即在不修改一个软件实体的基础上去扩展其功能。 | ※※※※※ |
里氏代换原则 | 在软件系统中,一个可以接收基类对象的地方一定可以接收一个子类对象。 | ※※※※ |
依赖倒转原则 | 要针对抽象层编程,而不要针对具体类编程。 | ※※※※※ |
接口隔离原则 | 使用多个专门的接口来取代一个统一的接口。 | ※※ |
合成复用原则 | 在复用功能时,应该尽量多使用组合和聚合关联关系,尽量少使用甚至不使用继承关系。 | ※※※※ |
迪米特法则 | 一个软件实体对其他实体的引用越少也好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的互相作用,而是通过引入一个第三者发生简介交互。 | ※※※ |
1. 单一职责原则
Single Responsibility Principle,SRP
单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小。
定义
定义一
:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中定义二
:就一个类而言,应该仅有一个引起它变化地原因。含义
一个类承担的职责越多,被复用地可能性越小。一个类承担的职责过多,相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责地运作。
类的职责主要包括:数据职责(属性)、行为职责(方法)。
单一职责原则是实现
高内聚、低耦合
的指导方针。
2. 开闭原则
开闭原则是面向对象的可复用设计的第一块基石,它是最重要的面向对象设计原则。
面向对象设计的目标。
定义
一个软件实体应当对扩展开放,对修改关闭。
也就是说,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不修改源代码的情况下改变这个模块的行为。
含义
在开闭原则的定义中,软件实体可以指一个软件模块、一个由多个类组成的局部结构或一个独立的类。
为了满足开闭原则,需要对系统进行抽象化设计,
抽象化
是开闭原则的关键。可以为系统定义一个相对稳定的抽象层,而将不同的实现行为在具体的实现层中完成。
“对可变性封装原则”,要求找到系统的可变性因素并将其封装起来。如将抽象层的不同实现封装到不同的具体类中,尽量不要将一种可变性和另一种可变性混合在一起。
百分百的开闭原则很难达到,但要尽可能使系统设计符合开闭原则。
里氏代换原则、依赖倒转原则等都是开闭原则的实现方法。
3. 里氏代换原则
定义
定义一
:(严格定义)如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都带u按o2时,程序P的行为没有变化,那么类型S是类型T的子类型。定义二
:(更易理解)所有医用基类(父类)的地方必须能透明地使用其子类地对象。含义
里氏代换原则可以通俗表述为:在软件中,如果能够使用基类对象,那么一定能够使用其子类对象。把基类都替换成它的子类,不会产生任何错误,反之不成立。
里氏代换原则
是实现开闭原则
的重要方式之一,是具体实现手段之一。 在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
注意:
子类地所有方法必须再父类中声明(或子类必须实现父类中声明地所有方法)
客户端针对父类编程,未在父类中声明的方法,无法直接使用父类来定义,只能使用子类,违背了里氏代换原则。
尽量把父类设计为抽象类或者接口。
让子类继承父类或实现父接口,并实现再父类中声明的方法。
增加新的功能可以通过增加一个新的子类来实现。
4. 依赖倒转原则
实现开闭原则的关键是抽象化,从抽象化导出具体化实现。
如果说,开闭原则是面向对象设计的目标,那依赖倒转原则就是面向对象设计的主要手段。
依赖倒转原则是系统抽象化的具体实现。
定义
表述一
:高层模块不应该依赖底层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。表述二
:要针对几口编程,不要针对实现编程。含义
依赖倒转原则就是指:代码要依赖于抽象的类,而不要依赖于具体的类;要针对接口或抽象类编程,而不是针对具体类编程。
在程序代码传参或组合聚合关系中,尽量使用层次高的抽象层类。
为确保该原则的应用,一个具体类应当只实现接口和抽象类中声明过的方法,不要给出多余的方法。
依赖倒转原则的常用实现方式之一是在代码中使用抽象类,而将具体类放在配置文件中。
两个概念
类之间的耦合
依赖倒转原则要求客户端依赖于抽象耦合,以抽象方式耦合是依赖倒转原则的关键。
里氏代换原则是依赖倒转原则的基础。
零耦合关系:
如果两个类之间没有任何耦合关系,称为零耦合。
具体耦合关系:
发生在两个具体类之(可实例化的类)间,由一个类对另一个具体类实例的直接引用产生。
抽象耦合关系:
发生在一个具体类和一个抽象类之间,或两个抽象类之间。
依赖注入
依赖注入是如何传递对象之间的依赖关系。
简单来说,依赖注入就是将一个类的对象传入另一个类,注入时应该尽量注入父类对象。
构造注入
通过构造函数注入实例变量。
设值注入
通过Setter方法注入实例变量。
接口注入
同故宫接口方法注入实例变量。
5. 接口隔离原则
接口隔离原则,要求将一些较大的接口进行细化,使用多个专门们的接口来替换单一的总接口。
定义
定义一
:客户端不应该依赖那些它不需要的接口。(接口指所定义的方法)定义二
:一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需要知道与之相关的方法即可。含义
每一个接口承担一种相对独立的角色。
这里的“接口”往往有两种含义:
①指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象;
接口的划分带来类型的划分。可以把接口理解成角色,每个角色都有特定的一个接口。
②某种语言具体的“接口”定义,有严格的定义和结构,如Java语言的interface。
接口尽量细化,接口中的方法应该尽量少。
6. 合成复用原则
为了降低类之间的耦合度,该原则倡导在复用功能时多用关联关系,少用继承关系。
定义
合成复用原则,又称为:组合/聚合复用原则。
定义为:尽量使用对象组合,而不是继承来达到复用的目的。
含义
在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之称为新对象的一部分。尽量使用组合/聚合瓜西,少用继承。
通过继承实现复用
- 优点:简单,子类可以覆盖父类的方法,易于扩展。
- 缺点:会破坏系统的封装性。(又称为“白箱”复用)如果基类发生改变,子类也要改变,没有足够的灵活性。
通过组合/聚合复用
是将一个类的对象作为另一个类的对象的一部分,或者说一个对象是由另一个或几个对象组合而成。(又称为“黑箱”复用)
耦合度相对继承关系而言较低。
7. 迪米特法则
迪米特法则用于降低系统的耦合度,使类与类之间保持松散的耦合关系。
定义
又称为,最少知识原则,有多种定义
定义一
:不要和“陌生人”说话。定义二
:只与你的直接朋友通信。定义三
:每一个软件单位对其他的单位都只有最少的知识,而且局限于哪些与本单位密切相关的软件单位。含义
要求限制软件实体之间通信的宽度和深度。
对于一个对象,其朋友包括:
- 当前对象本身(this);
- 以参数形式传入到当前对象方法种的对象;
- 当前对象的成员对象;
- 如果当前对象的成员对象使一个集合,那么集合在的元素也都是朋友;
- 当前对象所创建的对象。
依赖注入
几种?哪几种?
程序运行过程中,如果需要调用另一个对象时,无须在代码中创建被调用者,而是依赖于外部的注入。
3种:
构造注入:在构造函数种注入实例变量。
设值注入:通过
setxxx
方法注入实例变量接口注入:通过接口定义的方法,在接口实现中注入实例变量。
二、Java EE
C/S 和 B/S 架构
C/S 架构(客户端-服务器)
优点:
- 安全性好:C/S 程序部署在特定的客户端,系统的操作用户通常比较确定
- 效率高:客户端和服务器直接相连,数据传输比较快,系统运行效率比较高
- 个性化:可以根据需要对不同客户端上的程序进行界面和功能方面的定制,满足客户的个性化要求
- 稳定性强:C/S 结构比较稳定,有较强的事务处理能力,可以实现较复杂的业务逻辑
缺点:
- 适用面窄:C/S 程序通常部署于局域网中,能够使用的业务场景较少,适用范围较窄
- 用户群固定:C/S 架构系统需要安装客户端程序才可以使用,不适合面向不可知的用户
- 维护成本高:C/S 程序升级时需要对所有客户端程序进行升级,维护成本较高
B/S 架构(浏览器-服务器)
优点:
- 客户端免安装
- 交互性强
- 维护成本低
缺点:
- 浏览器兼容性差
- 效率低
- 安全风险高
- 实时性差
三层架构
三、设计模式
创建型设计模式
简单工厂:
- 优点:
- 创建和使用分离
- 客户端无需知道需要具体创建的类,只需要提供参数
- 通过配置文件,可以在不修改代码的同时增加新的类
- 缺点:
- 集中了所有产品创建逻辑,一旦不能工作,整个可能都受到影响。
- 会增加类的个数。
- 系统扩展困难。
- 使用了静态类,无法形成基于继承的等级结构。
把对象的创建和使用分离,遵从单一职责原则。
工厂方法模式,抽象工厂模式
工厂方法模式:
- 优点:
- 用户只需关心所需产品对应的工厂,无需知道具体产品类的名字。
- 缺点:
1.
单例模式:
保证每个类只有一个实体出现在计算机里面
结构型设计模式
适配器模式:
将一个类 地几口转换成用户希望地另一个接口,使得原本由于接口不兼容二不能一起工作的哪些类可以一起工作。无需修改食物内部结构。
装饰模式:
动态地给一个对象增加一些额外地职责,就增加对象功能来说,比生成子类更为灵活。
代理模式:
为其他对象提供一个代理,以控制对这个对象的访问。
行为型设计模式
命令模式:
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的擦偶哦。
将请求的发送者与请求的接收者分离,通过抽象编程的方式,使得相同的请求发送者可以作用于不同的请求接收者。
观察者模式:
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
一个对象的行为将影响到一个或多个其他对象的行为。
策略模式:
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
实现某功能存在多种方式,再不修改现有系统的基础上,可以灵活选择或更换实现方式,也可以使用新的实现方式。