一、数据流图
基础知识
-
数据流图(Data Flow Diagram,DFD)基本图形元素:
- 外部实体(External Agent)
表示存在于系统之外的对象,用来帮助用户理解系统数据的来源和去向 - 加工(Process)
- 数据存储(Data Store)
- 数据流(Data Flow)
加工、数据存储和数据流用于构建软件系统内部的数据处理模型
- 外部实体(External Agent)
-
外部实体:当前系统之外的人、物、外部系统
- 人:病人、医生、护理人员、巴士司机、机械师、会计等
- 物:传感器、控制器、采购部门等
- 外部系统:库存管理系统等
-
加工:把输入数据处理后得到输出数据
一个加工至少有一个输入数据流和一个输出数据流- 黑洞:加工只有输入没有输出
- 白洞:加工只有输出没有输入
- 灰洞:加工的输入数据不足以产生输出数据
-
数据流:由一组固定成分的数据组成,表示数据的流向
数据流的起点或终点必须有一个是加工
在DFD中,数据流的流向可以有以下几种:- 从一个加工流向另一个加工
- 从加工流向数据存储(写)
- 从数据存储流向加工(读)
- 从外部实体流向加工(输入)
- 从加工流向外部实体(输出)
固定题型
- 根据说明,给出实体名称
为了方便画图,实体可能会多次出现。
若出现多次,推荐优先从数据流少的实体进行确定 - 根据说明,给出数据存储名称
- 补充缺失的数据流
一般情况下,数据流条数(若不给定):分值/2~分值
数据流之间的顺序无要求
数据流名称尽量不要完全一样,后面出现的可以增加限定词,例如“通知”,“作业已批改的通知”- 父图子图平衡
- 加工至少有一个输入数据流和一个输出数据流
- 数据守恒(从说明找对应数据流)
16上
- 解析:“根据临时预定或变更预定的设备和设施需求,分配所需的设备(均能满足用户要求)和设施,更新相应的表”,特意提及了设备能满足要求,可能是在暗示设备,设施是分开表示的,结合0层数据流图,发现临时预定和变更预定传过来的也是“设备和设施需求”,则D3和D4是设施表和设备表
- 答案:
16下
官方答案如下,说明数据流并非要求名称不能一致
17下
tips:五分有六条数据流,说明条数和分数木啥太大关系~
随机题型
11上
- E1和E3之间不可以有数据流
因为数据流的起点和终点中必须有一个是加工(处理)
14上
- 图1-2中处理3只有输出数据流,没有输入数据流。
- D2和D3是黑洞,只有输入的数据流,没有输出的数据流。(是黑洞且与说明中缺少输出数据流才是所谓的问题,不要忽略后续的限定条件。因为数据存储没有要求必须有输入且有输出,题目中的是对应于说明缺少)
- 父图和子图不平衡,图1-2中没有图1-1中的数据流“维修情况”。
15上
- 解析:
“功能(6)发送通知 包含 创建通知 并 发送给学生或老师”,“分解加工(6) ”,则考虑分解为 创建通知 和 发送给学生或老师
进一步简述,后一个加工可以简化为发送通知 - 答案:
15下
-
解析:
-
答案:
把Email系统作为实体,并把通知的终点全部改为Email系统
16上
- 答案:
在图1-1和1-2中增加外部实体Email系统,并把素有发给客户的“确认消息”的数据流的终点改为Email系统
16下
在图1-1中增设外部实体“证券交易中心”,增加一条数据流“交易信息”,起点为“证券交易平台”,终点为“证券交易中心”
在图1-2中增设外部实体“证券交易中心”,增加从加工“证券交易(在线)”到此外部实体的数据流“交易信息”,增加从加工“证券交易(电话)”到此外部实体的数据流“交易信息”
17上
- 答案:
父图中加工的输入输出数据流必须和子图中的输入输出数据流在数量上和名字上相同;
父图中的一个输入(输出)数据流对应子图中几个输入(输出)数据流,而子图中组成这些数据流的数据项全体正好是父图中的这一条数据流。
17下
18上
or 父图中加工的输入输出数据流必须和子图中的输入输出数据流在数量上和名字上相同;父图中的一个输入(输出)数据流对应子图中几个输入(输出)数据流,而子图中组成这些数据流的数据项全体正好是父图中的这一条数据流。
18下
19上
-
解析
-
答案
二、数据库设计
基础知识
-
实体
- 弱实体
- 子实体
- 弱实体
-
属性
属性是实体某方面的特性。例如,学生实体具有学号、姓名、年龄和入学时间等属性。每个属性都有其取值范围,例如学号为001~999的六位整型数,姓名为十位的字符串,年龄的取值范围为18-60等。在同一实体集中,每个实体的属性及其域是相同的,但可能取不同的值。- 简单属性和复合属性
- 简单属性:原子的、不可再分的
- 复合属性:可以进一步再分(即划分为别的属性)
有时用户希望访问某个属性,有时希望访问属性的某个成分,那么在模式设计时可采用复合属性。例如,职工实体集的通信地址可以进一步分为右边、省、市、街道。
若不特别声明,通常指的是简单属性
- 单值属性和多值属性
- 单值属性:定义的属性对于一个特定的实体都只有单独的一个值。例如,对于一个特定的学生,只对应一个学号、姓名
- 多值属性:一个属性对应一组值。例如,职工可能有0个、1个或多个亲属,则职工的亲属的姓名可能有多个数目
- NULL属性
当实体在某个属性上没有值或属性值未知时,使用NULL值,表示无意义或不知道 - 派生属性
派生属性可以从其他属性得来。例如,职工实体集中有“参加工作时间”和“工作年限”属性,则“工作年限”的值可以由当前时间和参加工作时间得到,故“工作年限”就是一个派生属性
- 简单属性和复合属性
-
联系
在E-R模型中,联系用菱形表示,通常菱形框内写明联系名,并用无向边分别与有关实体连接起来,同时在无向边旁标注上联系的类型(1:1、1:n或m:n)。实体的联系分为实体内部的联系和实体与实体之间的联系。实体内部的联系反映数据在同一记录内部各字段间的联系。- 两个不同实体之间的联系
两个不同实体集之间存在以下三种联系类型:- 一对一(1:1)
指实体集E1中的一个实体最多只与实体集E2中的一个实体相联系
eg:电影院里一个座位只能做一个观众,则观众和座位之间是1:1的联系 - 一对多(1:n)
表示实体集E1中的一个实体可与实体集E2中的多个实体相联系
eg:部门和职工实体集,若一个职工只能属于一个部门,则这两个实体集之间应是一个1:n的联系 - 多对多(m:n)
表示实体集E1中的多个实体可与实体集E2中的多个实体相联系
eg:工程项目和职工实体集,若一个职工可以参加多个项目,一个项目可以有多个职工参加,则这两个实体集之间应是一个m:n的联系。
- 一对一(1:1)
- 两个以上不同实体集之间的联系
两个以上不同实体集之间存在1:1:1、1:1:n、1:m:n和r:m:n的联系。
eg:供应商Supp、项目Proj和零件Part之间多对多对多(r:m:n)的联系。表示供应商为多个项目供应多种零件,每个项目可用多个供应商供应的零件,每种零件可由不同的供应商供应的语义。
病房、病人和医生之间一对多对多(1:n:m)的联系。表示一个特护病房有多个病人和多个医生,一个医生只负责一个病房,一个病人只属于一个病房的语义。
- 两个不同实体之间的联系
-
关系模式:对关系的描述称为关系模式,由关系名和其属性集合构成,关系模式的格式为 关系名(属性名1,属性名2,……,属性名n)
-
候选码(或候选键):属性或属性组合,其值能够唯一地标识一个元组
-
主码(或主键):在一个关系中可能有多个候选码,从中选择一个作为主码
-
外码(或外键):若一个关系中的属性或属性组并非该关系的码,但它们是另外一个关系的码,则称其为该关系的外码
-
E-R图向关系模式转换的规则
-
一个实体型转换为一个关系模式,实体的名称就是关系模式的名称,实体的属性就是关系的属性,实体的码(关键字)就是关系的码
-
一个1:1联系可以转换为一个独立的关系模式,也可以和任意一端对应的关系模式合并
- 若转化为一个独立的模式,则与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,每个实体的码均是该关系的候选码。
eg:
部门(部门号,部门名,地址)
主任(姓名,性别,年龄)
领导(部门号,姓名)//当然姓名也是候选码 - 若与某一端实体对应的关系模式合并,则需要在该关系模式的属性中加入另一个关系模式的码和联系本身的属性
eg:
部门(部门号,部门名,地址,姓名)
主任(姓名,性别,年龄)
或者
部门(部门号,部门名,地址)
主任(姓名,性别,年龄,部门号)
- 若转化为一个独立的模式,则与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,每个实体的码均是该关系的候选码。
-
一个1:n联系可以转换为一个独立的关系模式,也可以和任意n端对应的关系模式合并
- 若转换为一个独立的模式,则与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,而关系的码为n端实体的码
eg:
部门(部门号,部门名,地址)
职工(姓名,性别,年龄)
所属(姓名,部门号)//主码只能是姓名 - 若和n端实体对应的关系模式合并,则需要在该关系模式的属性中加入1端关系模式的码和联系本身的码
eg:
部门(部门号,部门名,地址)
职工(姓名,性别,年龄,部门号)
- 若转换为一个独立的模式,则与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,而关系的码为n端实体的码
-
一个m:n联系转换为一个独立的关系模式,和该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,而关系的码为各实体码的组合
eg:
维修人员(职工号,姓名,部门)
设备(设备号,设备名,日期)
维修(职工号,设备号)//职工号,设备号分别也是维修的外键
-
三个以上实体间的一个多元联系可以转换为一个独立的关系模式,和该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,而关系的码为各实体码的组合
-
超类和子类的转换:超类、子类实体都可以转换为一个关系,并把超类实体的主码加到子类实体中。
下面E-R图中职员实体是飞行员、机械师和管理员实体的超类,超类和子类之间具有继承关系,其中各实体的属性为:
职员:职工号,姓名,性别,年龄,参加工作时间
飞行员:飞行小时,健康检查,飞机型号
机械师:学历,级别,专业职称
管理员:职务,职称
该E-R图转换为如下关系模式:
职员(职工号,姓名,性别,年龄,参加工作时间)
飞行员(职工号,飞行小时,健康检查,飞机型号)
机械师(职工号,职务,职称)
-
固定题型
- 根据说明,补充联系。注意联系名不能重名
- 根据E-R图,补充关系模式中的缺失属性,给出某几个关系的主键和外键。注意一个空代表着一个或多个属性
13下(1:n:m)
14上
-
解析
本题中的联系很隐晦~靠自己根据实体间的关系以及分数较高,猜测出家电和家电厂商的一对多联系。而客服、家电、客户间的多对多关系借助已有的图位置暗示。
-
答案
14下
-
解析:
-
答案:
16上(聚合)
-
解析
-
答案
19上(完整性约束)
-
解析
- 完整性约束
- 实体完整性(主键)
- 参照完整性(外键)
- 方法①:直接在增加的属性下面画上下划线(主键)或虚线(外键)
- 方法②:把空缺所在的关系模式中的主键和外键全部列出来一遍
- 完整性约束
- 答案
19下(“说明”联系及其类型)
- 答案
随机题型
09下(弱实体)
- 答案
11下
-
解析
-
答案
13下
14上
- 解析
本E-R图中的员工是电子商务公司的,所以电子商务公司的客户经理是该员工的子类,而基金公司的基金经理是个新实体 - 答案
14下(迷惑题,可忽略)
-
解析
-
答案
15下(命名冲突)
16上
-
解析
-
答案
16下(传递依赖)
- 解析
- 答案
17上
-
解析
-
答案
17下(全码)
18上
19上(增加属性,选择合适的补充位置)
-
解析
-
答案
19下(传递依赖)
- 答案
20下(关系模式问题&解决)
-
略
-
(a)经理号,电话
(b)地址,分公司编号,主管号(其中主管号是由业务部和主管间的一对一联系并入后增加)
(c)所属业务部编号 -
分公司关系模式中主键:分公司编号,外键:经理号
业务部关系模式中主键:业务部编号,外键:分公司编号,主管号 -
存在数据冗余,修改异常,插入异常,删除异常等问题
应该把职员关系模式分解为:
职员1(职员号,姓名,岗位,所属业务部编号,电话)
职员2(职员号, 家庭成员姓名,成员关系)
三、UML
基础知识
-
UML中有四种关系:依赖、关联、泛化、实现
-
依赖(Dependency)
依赖是两个事物间的语义关系,其中一个事物(独立事物)发生变化会影响另一个事物(依赖事物)的语义。
-
关联(Association)
关联是一种结构关系,它描述了一组链,链是对象之间的链接
在关联上可以标注重复度(multiplicity)(又称多重度)和角色(role)。其中重复度的理解类似于联系的类型
- 聚集(Aggregation)
聚集是一种特殊类型的关联,它描述了整体和部分间的结构关系。-
聚合
部分和整体的生命周期不一致,即部分可以脱离整体存在。例如班级和组成的同学,一个班级是一个整体,其中的同学是部分,但同学脱离了班级也可以存在。
-
组合
部分和整体的生命周期一致,部分不可以脱离整体。例如人和组成的细胞,人是一个整体,其中的细胞是部分,但是脱离了人,细胞也就不能存在了。
-
- 聚集(Aggregation)
-
泛化(Generalization)
泛化是一种特殊/一般关系,特殊元素(子元素)的对象可替代一般元素(父元素)的对象
-
实现(Realization)
实现是类元之间的语义关系,其中一个类元指定了由另一个类元保证执行的契约。在这种情况下会使用实现关系:一种是在接口和实现它们的类或构件之间;另一种是在用例和实现它们的协作之间。
-
-
图(Diagram)是一组元素的图形表示,大多数情况下把图画成顶点(代表事物)和弧(代表关系)的连通图。为了对系统进行可视化,可以从不同的角度画图,这样图是对系统的投影
UML2.0提供了13种图,分别是类图、对象图、用例图、序列图、通信图、状态图、活动图、构件图、组合结构图、部署图、包图、交互概览图和计时图。序列图、通信图、交互概览图和计时图都被称为交互图。-
类图(Class Diagram)展现了一组对象、接口、协作和它们之间的关系。在面向对象系统的建模中所建立的最常见的图就是类图。类图给出系统的静态设计视图。包含主动类的类图给出了系统的静态进程视图。
-
用例图
用例图(use case diagram)展现了一组用例、参与者(Actor)以及它们之间的关系
-
包含关系
-
扩展关系
用例和用例之间的关系
一个用例执行时,可能会发生一些特殊或可选的情况,这种情况就是这个用例的扩展用例。
-
泛化关系
参与者和参与者以及用例和用例之间的关系
-
固定题型
本道题型中出题方式顺序相对自由,不再区分真题中的固定与随机题型
- 根据说明,补充用例图
- 根据说明,补充类图
21下(用例之间的关系)
- U1:编写迷宫文件,U2:导入迷宫文件,U3:设置计时器
- U1、U2和建立迷宫是泛化关系,建立迷宫用例泛化U1、U2用例;
U3和操作机器人是包含关系,操作机器人用例包含U3用例
(用例和用例之间的关系有:包含include,扩展extend,泛化generalize) - C1:Robos
C2:Timer:PacMan
C4:Ghost
C5:Sersor
C6:FrontSensor
C7:ProxiSensor
C8:Maze
21上(用例之间的关系)
做这道题的内心OS:《曾经我也想过一了百了》
- A1:患者
A2:快递人员
A3:药师
U1:确认处方
观察用例图中功能除了“确认处方”都有对应用例,且也是患者有关的
U2:支付
U3:微信支付
U4:支付宝支付
类图中C1和C2,C3之间是泛化关系,找到说明中的有两个泛化的情况
①取药方式:自行到店取药 or 送药上门。
其中送药上门已经有对应用例,排除或者降低选择优先级
②支付方式:微信 or 支付宝
虽然形式隐蔽,没有出题人暗示的意思,但是软考题出得是挺随意的,不必担心。没有重复出现,为最优选择
- C1:支付方式
C2:微信支付
C3:支付宝支付
C4:处方
C5:药品
首先C1有两个不同特例,考虑支付或者取药方式。
题干中“支付成功之后,处方被发送给药师进行药品配制”,则当选择支付后,支付和处方有关联,考虑C4作为处方;后续与药师关联,与描述对应;
关于C5,和C4是单向关联,考虑快递人员或者药品,因为是单向的,药品更加合适(有什么处方会影响用什么药品,但是有什么药品和处方关系不大,主要看病症),快递人员没必要强调是单向的
- 包含include:一个用例包含另一个用例,当基本用例执行时,被包含用例一定会执行。包含关系由基本用例指向被包含用例,关系是一条带箭头的虚线,虚线上包含< < include>>
扩展extend:当一个用例执行时,可能会出现特殊情况和可选情况,这时会执行扩展用例。扩展关系由扩展用例指向基本用例,关系是一条带箭头的虚线,虚线上包含< < extend>>
泛化generalize:父用例泛化子用例,子用例继承父用例的所有属性和行为,且父用例可以出现的地方,子用例都可以将其替换。
20下(主要属性)
(类图错误:C4属于一般,应该指向C4)
- (1) A1:房产经纪
A2:系统管理员
U1:审批授权
U2:修改房产信息
U3:删除房产信息
(2)(a)< < include>>
(b)< < extend>>
“定期把售出和停售的房产信息进行归档,若确定不再销售某套房产时,才删除房产信息”,则U3删除房产信息属于特殊情况停售,则属于扩展(扩展用例指向一般用例)
想要U2修改房产信息,需要先导出房产信息来获得房产信息,属于包括(基本用例指向被包含用例)
- C1:Property
C2:House
C3:Cando
C4:user
C5:Manager
C6:Agent
首先C1和C4具有子类,则在用户和房产中考虑;
C5和C1有单向关联,则是人对房产进行操作,而管理房产信息的人员对房产透明,则C1是房产,C2,C3是住宅和公寓。
系统会记录房产经纪对房产负责的起止时间,且C6和房产间有AgentList,则房产经纪更可能是C6,从而C5是系统管理员
- 房产经纪负责每套房产的起始时间和终止时间
根据AgentList的英文意思,经纪人信息,会找房产经纪相关的信息,为了稳妥起见,可以把房产经济的基本信息和指出要记录的房产经济负责的每套房产的起止时间都加上。本题中把基本信息忽略的原因是问的是“主要”
19下(必要属性)
- A1:Receptionist
A 2:DentalStaff
A3:OfficeStaff
U1:Maintain patient info
U2:Record office visit info
U3:Print invoices
对于U1和U2的顺序,官方答案是反过来的,解析并没有表现出U1,U2不同的原因,没有将其区分。
- C1:PatientInvoice
C2:InsuranceInvoice
C3:Invoice
C4:Produre
C5:OfficeVisit
首先从上面做过的真题可知,图中的箭头不能深究,讲究个会意即可。所以类图中两个疑似泛化的箭头,可以理解为出题老师版本的泛化。则C3考虑为发票,C1和病人有关,则为给病人的发票;从而C2为给医保机构的发票。
剩下的可能类有接待员、办公人员,就诊信息,治疗。其中C5和病人有一对多的关系,C4和医护人员有多对多的关系以及C4和C3有多对多的关系。不是很明显,看下面的题目是否有辅助信息。给出C4,C5,Patient和DentalStaff的属性,会找图中的病人和医护人员的包含属性都已经给出,看有哪些其他给出属性的类。刚好有治疗和就诊信息,考虑这两个作为C4,C5。“病人在就诊时,可能需要接受多项治疗,每项治疗由多位医护人员为其服务”。病人和就诊有关,医护人员和治疗有关,且一次就诊对应一个病人,一个病人可以多次前来就诊,满足一对多,故C5为就诊信息。C4为治疗,一次就诊接受多次治疗,每次治疗由多位医护人员服务,满足多对多。
- C4:治疗项目名称、治疗项目描述、治疗的牙齿和费用
C5:就诊时间、就诊费用、支付代码、病人支付费用、医保支付费用
Patient:病人姓名、身份证号、出生日期、性别、首次就诊时间和最后一次就诊时间
DentalStaff:姓名、职位、身份证号、家庭住址和联系电话
19上(用例描述,需包含基本数据流和备选数据流)
-
A1:Buyer
A2:Warehouseman
A3:Dispathcer
U1:Register detail
U2:Print order
U3:Buy books -
基本事件流:顾客登录系统,浏览书籍信息,选择所需购买的书籍以购买数量,进入验证界面,输入注册码,生成订单
备选事件流:
(1)某种书籍的库存量为0,则顾客无法查询到该书籍信息
(2)书籍的购买数量超过库存量,提示库存不足
(3)注册码不正确,提示验证码错误
(4)顾客需要打印订单
-
C1:Customer
C2:Order
C3:Books
先从有属性的进行判断,确定C1,C3
然后剩余的给出英语名称的只有Order,代入C2可行,再确定C2
18下
- C1:SNSGroup
C2:SNSUser
C3:SNSAdmin - 观察者模式
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
适用场合:当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时;当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的 - 略
18上
- A1:Driver
A2:Central system
A3:Regional center
A4:Traffic advice center - U1:Underpaid transaction
U2:Record Illegal use
U3:Create transaction
U4:Record traffic event
U5:Charge card
从用例图中的两个扩展关系为切入点,根据用例列表,可能的情况有 基本用例:记录交易 ,扩展用例1:记录透支信息,扩展用例2:记录失败信息(作为特殊情况)。
和交易记录有关的是驾驶员(一定),中心系统,区域系统,不能确定继续找信息
U4只和A3,A4有关,磁卡充值和驾驶员有关,排除,则U4是记录交通信息。说明中和交通信息有关的只有区域系统和电台,则这两者为A3,A4
,从而A1,A2为驾驶员和中心系统
U5只剩磁卡充值,和驾驶员和中心系统有关,符合说明
- C1:Central
C2:Toll gantry
C3:Traffic lanes
C4:Radar sensor
C5:Radio transceiver
C6:Digital Camera
有三个组成部分,则C3是车道,从而C4,C5,C6分别是雷达、无线、相机,C2是龙门架
C1和区域系统有关联,则考虑驾驶员和中心系统,两个都是系统更协调,则C1为中心系统
17上(类的分类)
四、算法
基础
回溯
- N皇后问题
题型
- 代码填空
- 时空复杂度/算法策略
五、设计模式
简单工厂模式
属于创建型模式,但不属于23种设计模式之一。
- 定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
- 在简单工厂模式种用于被创建实例的方法通常称为静态static方法,故简单工厂模式又称为静态工厂方法Static Factory Method
- 需要什么产品就传入产品对应的参数,就可以获取所需要的产品对象,而无需知道其 实现过程
- eg:有一家饺子店,当客户需要某种饺子时,饺子店生成对应的饺子给客户,可以把饺子店视为工厂Factory,饺子视为产品Product,饺子的名称视为参数,饺子店根据不同的参数返回不同的饺子。比如,客户想要荠菜饺子,此处的荠菜就是参数,饺子店会根据参数荠菜返回荠菜饺子(在饺子店有荠菜饺子的前提下)
- 三类角色
- 工厂(核心):负责实现创建所有产品的内部逻辑
工厂类可以被外界直接调用,创建所需对象 - 抽象产品:工厂类所创建的所有对象的父类
封装了产品对象的公共方法,所有的具体产品为其子类对象 - 具体产品:简单工厂模式的创建目标
所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法。
- 工厂(核心):负责实现创建所有产品的内部逻辑
public class SimpleFactory {
public static void main(String[] args){
Product productA = Factory.createProduct("A");
productA.info();
Product productB = Factory.createProduct("B");
productB.info();
}
}
class Factory{
public static Product createProduct(String type){
Product product = null;
switch(type){
case "A":
product = new ProductA();
break;
case "B":
product = new ProductB();
break;
default:
System.out.println("no " + type + " type product");
}
return product;
}
}
abstract class Product{
public abstract void info();
}
class ProductA extends Product{
@Override
public void info(){
System.out.println("Product A");
}
}
class ProductB extends Product{
@Override
public void info() {
System.out.println("Product B");
}
}
工厂方法模式
- 意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类
- 结构
其中,Product定义工厂方法所创建的对象的接口
ConcreteProduct实现Product接口
Creator声明工厂方法,该方法返回一个Product类型的对象。Creator也可以定义一个工厂方法的默认实现,它返回一个默认的ConcreteProduct对象,可以调用工厂方法以创建一个Product对象
ConcreteCreator重定义工厂方法以返回一个ConcreteProduct实例 - 适用性
Factory模式适用于:- 当一个类不知道它所必须创建的对象的类时
- 当一个类希望由它的子类来指定它所创建对象时
- 当类把创建对象的职责委托给多个帮助子类中的某一个,并且希望把哪一个帮助子类是代理者这一信息局部化时
public class FactoryP{
public static void main(String[] args) {
IFactory factoryA = new FactoryA();
IProduct productA = factoryA.createProduct();
productA.info();
IFactory factoryB = new FactoryB();
IProduct productB = factoryB.createProduct();
productB.info();
}
}
interface IFactory{
public IProduct createProduct();//接口中的元素是public abstract的,可以省略
}
interface IProduct{
public void info();
}
class FactoryA implements IFactory{
@Override
public IProduct createProduct() {
return new ProductA1();
}
}
class FactoryB implements IFactory{
@Override
public IProduct createProduct(){
return new ProductB1();
}
}
class ProductA1 implements IProduct{
@Override
public void info() {
System.out.println("Product A1");
}
}
class ProductB1 implements IProduct{
@Override
public void info(){
System.out.println("Product B1");
}
}
抽象工厂模式
- 意图(特点):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类
- 结构:
其中,AbstractFactory声明一个创建抽象产品对象的操作接口
ConcreteFactory实现创建具体产品对象的操作
AbstractProduct是一类产品对象声明一个接口
ConcreteProduct定义一个将被相应的具体工厂创建的产品对象,实现AbstractProduct接口
Client仅使用由AbstractFactory和AbstractProduct类声明的接口 - 适用性
Abstract Factory模式适用于:- 一个系统要独立于它的产品的创建、组合和表示时
- 一个系统要由多个产品系列中的一个来配置时
- 当要强调一系列相关的产品对象的设计以便进行联合使用时
- 当提供一个产品类库,只想显示它们的接口而非实现时
public class AbstractFactory {
public static void main(String[] args) {
Factory factory1 = new Fractory1();
ProductA productA = factory1.createProductA();
productA.info();
Factory factory2 = new Factory2();
ProductB productB = factory2.createProductB();
productB.info();
}
}
interface Factory{
public ProductA createProductA();
public ProductB createProductB();
}
class Fractory1 implements Factory{
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
class Factory2 implements Factory{
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
interface ProductA{
public void info();
}
interface ProductB{
public void info();
}
class ProductA1 implements ProductA{
@Override
public void info() {
System.out.println("Product A1");
}
}
class ProductA2 implements ProductA{
@Override
public void info() {
System.out.println("Product A2");
}
}
class ProductB1 implements ProductB{
@Override
public void info() {
System.out.println("Product B1");
}
}
class ProductB2 implements ProductB{
@Override
public void info() {
System.out.println("Product B2");
}
}
生成器模式Builder
- 意图:把一个复杂对象的构建和它的表示分离,使得同样的构建过程可以构建不同的表示
- 结构
其中,Builder为创建一个Product对象的各个部件指定抽象接口
ConcreteBuilder实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,提供一个检索产品的接口
Director构造一个使用Builder接口的对象
Product表示被构造的复杂对象。ConcreteBUilder创建该产品的内部表示并定义它的装配过程。包含定义组成组件的类,包括把这些组件装配成最终产品的接口 - 适用性
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时
- 当构造过程必须允许被构造的对象有不同的表示时
原型模式Prototype
- 意图:用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象
- 结构
Prototype声明一个复制自身的接口
ConcretePrototype实现一个复制自身的操作
Client让一个原型复制自身从而创建一个新的对象 - 适用性
- 当一个系统应该独立于它的产品创建、构成和表示时
- 当要实例化的类在运行时指定时,例如,通过动态装载
- 为了避免创建一个与产品类层次平行的工厂类层次时
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们,可能比每次用合适的状态手工实例化该类更方便一些
适配器模式Adapter
- 意图:把一个类的接口转换为客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
- 结构
类适配器使用多重继承对一个接口和另一个接口进行匹配。对象适配器依赖于对象组合。其中:
Target定义Client使用的和特定领域相关的接口
Client和符合Target接口的对象协同
Adaptee定义一个已经存在的接口,这个接口需要适配
Adapter对Adaptee的接口和Target接口进行适配
- 适用性
- 想使用一个已经存在的类,而它的接口不符合要求
- 想创建一个可以复用的类,该类可以和其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作
- (仅适用于对象Adapter)想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口
桥接模式Bridge
- 意图:把抽象部分和其实现部分分离,使它们都可以独立地变化
- 结构
其中Abstraction定义抽象类的接口,维护一个指向Implementor类型对象的指针
RefinedAbstraction扩充由Abstraction定义的接口
Implementor定义实现类的接口,该接口不一定要与Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来说,Implementor接口仅提供基本操作,而Abstraction定义了基于这些基本操作的较高层次的操作
ConcreteImplementor实现Implementor接口并定义它的具体实现 - 适用性
- 不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这是Bridge模式使得开发者可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译
- (C++)想对客户完全隐藏抽象的实现部分
- 有许多类要生成的类层次结构
- 想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点
组合模式Composite
- 意图:把对象组合成树型结构以表示“整体-部分”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性
- 结构
Component为组合中的对象声明接口;在适当情况下实现所有类共有接口的默认行为;声明一个接口用于访问和管理Component的子组件;(可选)在递归结构中定义一个接口,用于访问一个父组件,并在合适的情况下实现它。
Leaf在组合中表示叶节点对象,叶节点没有子节点;在组合中定义图元对象的行为
Composite定义有子组件的那些组件的行为;存储子组件;在Component接口中实现和子组件有关的操作
Client通过Component接口操纵组合组件的对象
- 适用性
- 想表示对象的部分-整体层次结构
- 希望用户忽略组合对象和单个对象的不同,用户将统一地使用组合结构中的所有对象
装饰器模式Decorator
- 意图:动态地给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更加灵活
- 结构
Component定义一个对象接口,可以给这些对象动态地添加职责
ConcreteComponent定义一个对象,可以给这个对象添加一些职责
Decorator维持一个指向Component对象的指针,并定义一个与Component接口一致的接口
ConcreteDecorator向组件添加职责 - 适用性
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
- 处理那些可以撤销的职责
- 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类
16下
享元模式Flyweight
- 意图:运用共享技术有效地支持大量细粒度的对象
- 结构
Flyweight描述一个接口,通过这个接口Flyweight可以接受并作用于外部状态
ConcreteFlyweight实现Flyweight接口,并为内部状态(如果有)增加存储空间
ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的,即它必须独立于ConcreteFlyweight对象的场景
并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次,UnsharedConcreteweight对象通常把ConcreteFlyweight对象作为子节点
FlyweightFactory创建并管理Flyweight对象;确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者不存在时创建一个实例
Client维持一个对Flyweight的引用;计算或存储一个或多个Flyweiht的外部状态 - 适用性
- 一个应用程序使用了大量的对象
- 完全由于使用大量的对象,造成很大的存储开销
- 对象的大多数状态都可变为外部状态
- 如果删除对象的外部状态,则可以用相对较少的共享对象取代很多组对象
- 应用程序不依赖于对象标识。由于Flyweight对象可以被共享,则对于概念上明显有别的对象,标识测试将返回真值
命令模式Command
- 意图:把一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化;对请求排队或记录请求日志以及支持可撤销的操作
- 结构
Command声明执行操作的接口
ConcreteCommand把一个接收者对象绑定于一个动作;调用接收者相应的操作,以实现Execute
Client创建一个具体命令对象并设定它的接收者
Invoker要求该命令执行这个请求
Receiver知道如何实施和执行一个请求相关的操作。任何类都可能作为一个接收者 - 适用性
- 抽象出待执行的动作以参数化某对象。
- 在不同的时刻指定、排列和执行请求
- 支持取消操作
- 支持修改日志
- 用构建在原语操作上的高层操作构造一个系统
14下
-
解析
-
答案
观察者模式Observer
- 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
- 结构
Subject(目标)知道它的观察者,可以有任意多个观察者观察同一个目标;提供注册和删除观察者对象的接口
Observer(观察者)为那些在目标发生改变时需获得通知的对象定义一个更新接口
ConcreteSubject(具体目标)把有关状态存入各ConcreteOberver对象;当它的状态发生改变时,向它的各个观察者发出通知
ConcreteObserver(具体观察者)维护一个指向ConcreteSubject对象的引用,存储有关状态,这些状态应与目标的状态保持一致;实现Observer的更新接口,以使自身状态和目标的状态保持一致
- 适用性
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,把这两者封装在独立的对象中以使它们可以各自独立地改变和复用
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时
- 当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的
14上
-
解析
-
答案
状态模式
-
意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
-
结构
Context(上下文)定义客户感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态
State(状态)定义一个接口以封装与Context的一个特定状态相关的行为
ConcreteState(具体状态子类)每个子类实现和Context的一个状态相关的行为 -
适用性
- 一个对象的行为决定它的状态,且它必须在运行时刻根据状态改变它的行为
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式把每一个条件分支放入一个独立的类中。这使得开发者可以根据对象自身的情况把对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化
11下
-
解析
-
答案
18下
策略模式
- 意图:定义一系列算法,把它们一个个封装起来,且使它们可以相互替换。此模式使得算法可以独立于使用它们的客户而变化
- 结构
Strategy(策略)定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法
ConcreteStrategy(具体策略)以Strategy接口实现某具体算法
Context(上下文)用一个ConcreteStrategy对象来配置,维护一个对Strategy对象的引用;可定义一个接口来让Strategy访问它的数据 - 适用性
- 许多相关的类仅仅是行为不同
- 需要使用一个算法的不同变体
- 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构
- 一个类定义了多种行为,且这些行为在这个类的操作中以多个条件语句的形式出现,把相关的条件分支移入它们各自的Strategy类中,以代替这些条件语句
10上
访问者模式Visitor
-
意图:表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作
-
结构
Visitor(访问者)为该对象结构中ConcreteElement的每一个类声明一个Visit操作。该操作的名字和特征标识了发送Visit请求给该访问者的那个类,这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
ConcreteVisitor(具体访问者)实现每个有Visitor声明的操作,每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累计结果
Element(元素)定义以一个访问者为参数的Accept操作。
ConcreteElement(具体元素)实现以一个访问者为参数的Accept操作。
ObjectStructure(对象结构)能枚举它的元素:可以提供一个高层的接口以允许该访问者它的元素:可以是一个组合或一个集合,如一个列表或一个无序集合 -
适用性
- 一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而又想要避免这些操作“污染”这些对象的类。Visitor使得用户可以把相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。
15上
中介者模式Mediator
-
意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,且可以独立地改变它们之间的交互。
-
结构
Mediator(中介者)定义一个接口用于各同事(Colleague)对象通信
ConcreteMediator(具体中介者)通过协调各同事对象实现协作行为;了解并维护它的各个同事
Colleague class(同事类)知道它的中介者对象;每一个同事类对象在需要和其他同事通信的时候和它的中介者通信 -
适用性
- 一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类
20下