前置知识
学习设计模式前需要掌握的基础知识
面向对象基础
设计模式建立在面向对象编程(OOP)的基础之上。理解类、对象、封装、继承、多态等核心概念是学习设计模式的前提。
类与对象
类是对象的蓝图或模板,定义了对象具有的属性和方法。对象是类的实例,是内存中实际存在的实体。
Example.java
封装
封装是将数据(属性)和操作数据的方法绑定在一起,并隐藏内部实现细节。通过访问修饰符(public、private、protected)控制访问权限。
Example.java
继承
继承允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码复用和层次化分类。
Example.java
多态
多态允许子类重写父类的方法,使得同一个方法调用可以有不同的行为。这是实现"针对接口编程,而非实现编程"的基础。
Example.java
抽象类与接口
抽象类是不能实例化的类,通常包含抽象方法。接口定义了一组方法的契约,实现类必须遵守。两者都用于定义规范。
Example.java
组合 vs 继承
继承是"是一个"(is-a)关系,组合是"有一个"(has-a)关系。设计模式更推崇组合,因为它更灵活,耦合度更低。
Example.java
组合 vs 继承 对比表
继承和组合是代码复用的两种主要方式,设计模式更倾向于使用组合。
Example.java
接口 vs 抽象类 对比表
接口和抽象类都用于定义规范,但使用场景不同。
Example.java
UML类图基础
UML(统一建模语言)类图是设计模式的图形化表示方式。掌握类图的阅读能力是理解和应用设计模式的关键。
类的表示
在UML类图中,类用一个矩形表示,分为三层:类名、属性、方法。+ 表示 public,- 表示 private,# 表示 protected。
classDiagram
class Animal {
-name: String
+getName(): String
+setName(name: String): void
}
class Dog {
-breed: String
+bark(): void
+getBreed(): String
}Example.java
继承(Generalization)
继承关系用带空心三角形的实线表示,箭头指向父类。表示"is-a"关系。
classDiagram
Animal <|-- Dog
class Animal {
#name: String
}
class Dog {
+bark(): void
}Example.java
实现(Realization)
实现关系用带空心三角形的虚线表示,箭头指向接口。表示类实现了接口定义的契约。
classDiagram
class Flyable {
<<interface>>
+fly(): void
}
Flyable <|.. Bird
class Bird {
+fly(): void
}Example.java
关联(Association)
关联关系用实线箭头表示,表示一个类知道另一个类。可以是双向的(无箭头)或单向的(有箭头)。
classDiagram
Teacher "1" --> "0..*" Student : teachesExample.java
依赖(Dependency)
依赖关系用虚线箭头表示,表示一个类临时使用另一个类。通常体现在方法参数、局部变量或返回值中。
classDiagram
Person ..> Tool : usesExample.java
聚合(Aggregation)
聚合是特殊的关联关系,表示"整体-部分"关系,但部分可以独立存在。用空心菱形表示。
classDiagram
Department o-- Employee : containsExample.java
组合(Composition)
组合是更强的聚合关系,部分不能独立于整体存在。用实心菱形表示。整体销毁时,部分也随之销毁。
classDiagram
Car *-- Engine : ownsExample.java
综合示例:设计模式中的类图
以观察者模式为例,展示一个完整的设计模式类图。
classDiagram
class Subject {
<<interface>>
+attach(Observer): void
+detach(Observer): void
+notify(): void
}
class ConcreteSubject {
-state: String
+getState(): String
+setState(state: String): void
}
class Observer {
<<interface>>
+update(): void
}
class ConcreteObserver {
-subject: Subject
+update(): void
}
Subject <|.. ConcreteSubject
Observer <|.. ConcreteObserver
Subject "1" o-- "0..*" Observer : observers
ConcreteObserver --> ConcreteSubject : observesSOLID设计原则
SOLID是面向对象设计的五个基本原则,由罗伯特·C·马丁提出。遵循这些原则可以使软件更易于理解、维护和扩展。
单一职责原则 (SRP)
一个类应该只有一个引起它变化的原因。换句话说,一个类应该只负责一项职责。
Example.java
开闭原则 (OCP)
软件实体应该对扩展开放,对修改关闭。通过抽象和继承实现新功能,而不是修改现有代码。
Example.java
里氏替换原则 (LSP)
子类型必须能够替换其基类型,而程序的行为不变。这是确保继承关系正确使用的重要原则。
Example.java
接口隔离原则 (ISP)
客户端不应该被迫依赖它们不使用的方法。应该将大接口拆分为多个小接口。
Example.java
依赖倒置原则 (DIP)
高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
Example.java
常见术语
理解设计模式中的常用术语,有助于更好地阅读和交流设计模式相关的知识。
耦合 (Coupling)
模块之间的相互依赖程度。低耦合意味着模块间依赖少,修改一个模块对其他模块影响小。设计模式的目标之一就是降低耦合。
内聚 (Cohesion)
模块内部各元素之间的关联程度。高内聚意味着模块功能单一、职责明确。高内聚通常伴随着低耦合。
扩展点 (Extension Point)
在软件设计中预留的接口或抽象类,允许在不修改现有代码的情况下添加新功能。设计模式通常围绕扩展点展开。
框架 vs 库
库是一组你可以调用的工具函数,控制权在你。框架是一个骨架,你填充代码,控制权在框架。设计模式常用于框架的设计。
客户端 (Client)
在设计模式语境中,指使用某个类、接口或系统的代码。不一定是最终用户,而是调用方代码。
具体类 vs 抽象类
具体类可以直接实例化,包含完整实现。抽象类不能直接实例化,通常包含抽象方法,需要子类实现。设计模式鼓励面向抽象编程。
委托 (Delegation)
一个对象将某个操作交给另一个对象来处理。这是实现复用的一种方式,也是许多设计模式的基础。
变化点 (Variation Point)
软件中可能发生变化的地方。设计模式的核心思想就是封装变化点,使系统更易于应对需求变更。
常见误区
在学习面向对象和设计模式的过程中,有一些常见的误解和误用。了解这些误区可以帮助你避免走弯路。
误区一:过度使用继承
很多初学者认为继承是代码复用的最佳方式,于是到处使用继承。实际上,继承是紧耦合的,父类的改变会影响所有子类。设计模式更推荐组合而非继承。
Example.java
误区二:把所有代码都放到一个类
这是典型的"上帝类"(God Class)反模式。一个类做了太多事情,违反了单一职责原则。应该将功能拆分到多个小类中。
误区三:过度设计
为了使用设计模式而使用设计模式,会让简单的代码变得复杂。设计模式是用来解决特定问题的,没有问题就不要强行套用。记住:KISS原则(Keep It Simple, Stupid)。
误区四:忽视接口隔离
创建大而全的接口,强迫客户端依赖它们不需要的方法。应该将大接口拆分为多个小接口,每个接口只包含相关的方法。
误区五:滥用单例模式
单例模式虽然简单,但会引入全局状态,使代码难以测试。在现代开发中,依赖注入通常是更好的选择。
误区六:认为设计模式是银弹
设计模式是解决特定问题的经验总结,不是万能的。盲目套用设计模式而不理解其背后的思想,会导致代码质量下降。
学习建议
掌握以下学习方法和技巧,可以帮助你更高效地理解和应用设计模式。
如何阅读类图
1. 先看类名:了解每个类的职责
2. 再看关系:理解类之间的关联、继承、依赖关系
3. 关注交互:顺着方法调用关系理解协作流程
4. 对照代码:将类图与实际代码对照,加深理解
2. 再看关系:理解类之间的关联、继承、依赖关系
3. 关注交互:顺着方法调用关系理解协作流程
4. 对照代码:将类图与实际代码对照,加深理解
如何理解设计原则
1. 先理解问题:每个原则都是为了解决特定问题
2. 看正例反例:对比遵循和违反原则的例子
3. 实践应用:在实际项目中尝试应用
4. 反思总结:思考原则带来的好处和代价
2. 看正例反例:对比遵循和违反原则的例子
3. 实践应用:在实际项目中尝试应用
4. 反思总结:思考原则带来的好处和代价
学习设计模式的正确姿势
1. 先学思想:理解面向对象设计原则
2. 再学模式:学习具体的设计模式
3. 看实际应用:研究框架源码中的应用
4. 动手实践:在自己的项目中尝试使用
5. 反思总结:思考什么场景适合什么模式
2. 再学模式:学习具体的设计模式
3. 看实际应用:研究框架源码中的应用
4. 动手实践:在自己的项目中尝试使用
5. 反思总结:思考什么场景适合什么模式
推荐学习资源
书籍:
- 《Head First 设计模式》(入门首选)
- 《设计模式:可复用面向对象软件的基础》(GoF经典)
- 《重构:改善既有代码的设计》
网站:
- Refactoring.Guru(图文并茂)
- Java Design Patterns(实际案例)
实践:
- 阅读 Spring、JDK 源码
- 参与开源项目
- 重构自己的项目
- 《Head First 设计模式》(入门首选)
- 《设计模式:可复用面向对象软件的基础》(GoF经典)
- 《重构:改善既有代码的设计》
网站:
- Refactoring.Guru(图文并茂)
- Java Design Patterns(实际案例)
实践:
- 阅读 Spring、JDK 源码
- 参与开源项目
- 重构自己的项目