一、设计模式概述
1 统一建模语言(UML)
UML是一种建模语言,而不是一种方法。
1.1 类图(掌握)
1.1.1 类图的基本表示
类的图形符号:
类在UML中用矩形框表示,分为三部分:
示例:
类名(顶部矩形框):使用领域术语,明确无歧义。
属性(中间矩形框):描述类的成员变量,可见性用
+
(public)、#
(protected)、-
(private)表示。操作(底部矩形框):描述类的成员方法。
1.1.2 类图中的关系
UML类图中常见的关系有以下五种:
泛化(Generalization):
关系:继承关系,表示“is-a”关系(子类是父类的特化)。
箭头:带三角箭头的实线,箭头指向父类。
代码实现:通过继承关键字(如Java的
extends
)。
聚合(Aggregation):
关系:整体与部分的关系,部分可独立存在(“has-a”关系)。
箭头:带空心菱形的实线,菱形指向整体。
代码实现:通过成员变量表示。
示例:汽车(整体)与轮胎(部分)。
组合(Composition):
关系:比聚合更强的整体与部分关系,部分不能独立存在(“contains-a”关系,同生共死)。
箭头:带实心菱形的实线,菱形指向整体。
代码实现:通过成员变量表示。
示例:公司(整体)与部门(部分)。
依赖(Dependency):
关系:临时性的使用关系,耦合度最弱。
箭头:带箭头的虚线,指向被依赖的类。
代码实现:通过局部变量、方法参数或静态方法调用。
特点:仅在方法执行期间存在。
关联(Association):
- 关系:持久的拥有关系,一个类知道另一个类的属性和方法。
- 箭头:带普通箭头的实线,指向被拥有者。
- 类型:
双向关联:默认关联,无箭头或双箭头。
单向关联:单箭头表示方向。
自关联:类的属性类型为自身。
多重性关联:表示数量关系(如1..*
、0..1
)。
1.1.3 其他重要概念
接口与实现关系:
类实现接口时,用带空心三角形的虚线表示(UML中为“实现”关系)。
示例:
class A implements InterfaceB
。
多重性表示:
在关联线上标注数字或范围(如
1
、3..7
、*
表示未确定数量)。
通过掌握这些UML类图知识,可以更清晰地设计和分析面向对象的软件系统。
2.软件设计模式概述(理解)
2.1 软件设计模式简述
设计模式是对软件设计经验总结,是对软件设计中反复出现的设计问题的成功解决方案的描述。
2.2 设计模式的四个基本要素
模式名称(Pattern Name)
设计模式的标识符(如“单例模式”),便于交流与记忆。
问题(Problem)
描述模式的应用场景及待解决的核心问题(如“如何确保一个类仅有一个实例”)。
解决方案(Solution)
提供模式的设计结构,包括类/对象的角色、协作方式(如“通过私有构造函数和静态方法控制实例化”)。
效果(Consequences)
分析模式的优缺点,包括灵活性、性能、复用性等(如“单例模式节省资源,但可能引入全局状态”)。
2.3 软件设计模式的分类
1. 按目的分类
创建型模式(Creational)
关注对象的创建机制,解耦实例化过程。
示例:单例模式、工厂方法模式、抽象工厂模式。
结构型模式(Structural)
处理类或对象的组合,形成更大结构。
示例:适配器模式、装饰模式、代理模式。
行为型模式(Behavioral)
定义对象间的交互与职责分配。
示例:观察者模式、策略模式、模板方法模式。
2. 按范围分类
类模式
通过继承关系在编译时静态确定(如模板方法模式)。
对象模式
通过对象组合在运行时动态确定(如组合模式、策略模式)。
2.3 经典模式示例(GoF 23种)
分类 | 模式名称 | 应用场景 |
---|---|---|
创建型 | 单例模式(Singleton) | 全局唯一配置管理器。 |
结构型 | 适配器模式(Adapter) | 兼容不兼容接口的系统集成。 |
行为型 | 观察者模式(Observer) | 事件通知系统(如GUI事件处理)。 |
适用场景:需频繁扩展的系统、多人协作项目、复用现有架构时。
2.4 反射机制
Java反射(Java Reflection)是指在程序运行时获取已知名称的类或已有对象的相关信息的一种机制,包括类的方法、属性、父类等信息,还包括实例的创建和实例类型的判断等。
二、面向对象设计七大原则(理解)
1. 单一职责原则(Single Responsibility Principle, SRP)
定义:一个类应该仅有一个引起它变化的原因(即只承担一个职责)。
核心思想:
高内聚:将不同职责分离到不同的类中。
避免因职责过多导致代码难以复用或修改。
示例:
学生工作管理程序中,将“生活辅导”和“学业指导”分给辅导员和学业导师两个类。
2. 开闭原则(Open-Closed Principle, OCP)
定义:软件实体(类、模块、函数等)应对扩展开放,对修改关闭。
核心思想:
通过抽象(接口或抽象类)定义稳定层,通过具体实现类扩展功能。
遵循“对可变性封装原则”(EVP)。
示例:
Windows主题设计:通过抽象主题接口支持新主题的扩展,无需修改原有代码。
3. 里氏代换原则(Liskov Substitution Principle, LSP)
定义:子类必须能够替换父类,且程序行为不变。
核心思想:
子类可以扩展父类功能,但不能改变父类原有行为。
避免因重写父类方法导致程序错误。
示例:
“几维鸟不会飞”问题:应重构为“鸟”和“几维鸟”继承自更通用的“动物”类。
4. 依赖倒转原则(Dependency Inversion Principle, DIP)
定义:高层模块不应依赖低层模块,二者都应依赖抽象;抽象不应依赖细节,细节应依赖抽象。
核心思想:
面向接口编程,通过依赖注入(DI)解耦。
使用接口或抽象类声明变量、参数和返回值类型。
示例:
顾客购物程序应依赖抽象的“Shop接口”,而非具体的“韶关网店”类。
5. 接口隔离原则(Interface Segregation Principle, ISP)
定义:客户端不应被迫依赖它不需要的接口。
核心思想:
将大接口拆分为多个小接口,每个接口承担单一角色。
提供“定制服务”,避免接口臃肿。
示例:
打印机接口拆分为“打印”、“扫描”等独立接口,避免多功能设备强制实现无关方法。
6. 合成复用原则(Composite Reuse Principle, CARP)
定义:优先使用组合/聚合,而非继承来复用代码。
核心思想:
组合/聚合(“has-a”关系)比继承(“is-a”关系)更灵活。
降低耦合,支持运行时动态调整。
示例:
汽车分类管理程序中,通过组合“动力源”和“颜色”属性避免继承爆炸。
7. 迪米特法则(Law of Demeter, LoD)
定义:一个对象应尽可能少地与其他对象交互(最少知识原则)。
核心思想:
通过“中介”转发调用,降低直接耦合。
只与直接朋友(成员变量、方法参数、返回值)通信。
示例:
明星通过经纪人处理粉丝请求,而非直接与粉丝交互。