前置知识

学习设计模式前需要掌握的基础知识

面向对象基础

设计模式建立在面向对象编程(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 : teaches
Example.java

依赖(Dependency)

依赖关系用虚线箭头表示,表示一个类临时使用另一个类。通常体现在方法参数、局部变量或返回值中。
classDiagram
    Person ..> Tool : uses
Example.java

聚合(Aggregation)

聚合是特殊的关联关系,表示"整体-部分"关系,但部分可以独立存在。用空心菱形表示。
classDiagram
    Department o-- Employee : contains
Example.java

组合(Composition)

组合是更强的聚合关系,部分不能独立于整体存在。用实心菱形表示。整体销毁时,部分也随之销毁。
classDiagram
    Car *-- Engine : owns
Example.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 : observes

SOLID设计原则

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. 对照代码:将类图与实际代码对照,加深理解

如何理解设计原则

1. 先理解问题:每个原则都是为了解决特定问题
2. 看正例反例:对比遵循和违反原则的例子
3. 实践应用:在实际项目中尝试应用
4. 反思总结:思考原则带来的好处和代价

学习设计模式的正确姿势

1. 先学思想:理解面向对象设计原则
2. 再学模式:学习具体的设计模式
3. 看实际应用:研究框架源码中的应用
4. 动手实践:在自己的项目中尝试使用
5. 反思总结:思考什么场景适合什么模式

推荐学习资源

书籍
- 《Head First 设计模式》(入门首选)
- 《设计模式:可复用面向对象软件的基础》(GoF经典)
- 《重构:改善既有代码的设计》

网站
- Refactoring.Guru(图文并茂)
- Java Design Patterns(实际案例)

实践
- 阅读 Spring、JDK 源码
- 参与开源项目
- 重构自己的项目