设计模式

设计模式

目录


面向对象设计原则

单一职责原则 (Single Responsibility Principle)

定义:一个类应该只有一个引起它变化的原因。

核心思想:一个类只负责一项职责。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 不好的设计 - 一个类承担多个职责
class User {
public void saveUser() { /* 保存用户 */ }
public void sendEmail() { /* 发送邮件 */ }
public void calculateSalary() { /* 计算薪资 */ }
}

// 好的设计 - 分离职责
class UserRepository {
public void saveUser() { /* 保存用户 */ }
}
class EmailService {
public void sendEmail() { /* 发送邮件 */ }
}
class SalaryCalculator {
public void calculateSalary() { /* 计算薪资 */ }
}

开闭原则 (Open/Closed Principle)

定义:软件实体应该对扩展开放,对修改关闭。

核心思想:通过添加新代码来扩展功能,而不是修改已有代码。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 不好的设计 - 添加新支付方式需要修改原有代码
class PaymentProcessor {
public void processPayment(String type) {
if (type.equals("ALIPAY")) {
// 支付宝支付
} else if (type.equals("WECHAT")) {
// 微信支付
}
// 新增支付方式需要修改这里
}
}

// 好的设计 - 对扩展开放
interface Payment {
void pay();
}
class AliPay implements Payment {
public void pay() { /* 支付宝 */ }
}
class WeChatPay implements Payment {
public void pay() { /* 微信 */ }
}
class PaymentProcessor {
public void processPayment(Payment payment) {
payment.pay();
}
}

里氏替换原则 (Liskov Substitution Principle)

定义:所有引用基类的地方必须能透明地使用其子类的对象。

核心要点

  1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
  2. 子类可以增加自己特有的方法
  3. 子类重写/重载父类方法时,前置条件更宽松,后置条件更严格

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 不好的设计 - 正方形继承矩形,违反LSP
class Rectangle {
protected int width, height;
public void setWidth(int w) { width = w; }
public void setHeight(int h) { height = h; }
public int getArea() { return width * height; }
}
class Square extends Rectangle {
@Override
public void setWidth(int w) {
super.setWidth(w);
super.setHeight(w);
}
@Override
public void setHeight(int h) {
super.setWidth(h);
super.setHeight(h);
}
}

// 好的设计 - 提取共同基类
abstract class Shape {
public abstract int getArea();
}
class Rectangle extends Shape {
private int width, height;
public void setWidth(int w) { width = w; }
public void setHeight(int h) { height = h; }
public int getArea() { return width * height; }
}
class Square extends Shape {
private int side;
public void setSide(int s) { side = s; }
public int getArea() { return side * side; }
}

依赖倒转原则 (Dependency Inversion Principle)

定义:高层模块不应依赖于底层模块,它们都应该依赖抽象。抽象不应依赖于细节,细节应该依赖于抽象。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 不好的设计 - 高层依赖低层
class OrderService {
private MySQLOrderDao dao = new MySQLOrderDao();
public void saveOrder() { dao.save(); }
}
class MySQLOrderDao {
public void save() { /* MySQL保存 */ }
}

// 好的设计 - 依赖抽象
interface OrderDao {
void save();
}
class MySQLOrderDao implements OrderDao {
public void save() { /* MySQL保存 */ }
}
class OrderService {
private OrderDao dao;
public OrderService(OrderDao dao) { this.dao = dao; }
public void saveOrder() { dao.save(); }
}

接口隔离原则 (Interface Segregation Principle)

定义:客户端不应该依赖它不需要的接口。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 不好的设计 - 接口过于臃肿
interface Animal {
void fly();
void swim();
void run();
}
class Dog implements Animal {
public void fly() { /* 狗不会飞,空实现 */ }
public void swim() { /* 狗会游泳 */ }
public void run() { /* 狗会跑 */ }
}

// 好的设计 - 接口分离
interface Flyable { void fly(); }
interface Swimmable { void swim(); }
interface Runnable { void run(); }
class Dog implements Swimmable, Runnable {
public void swim() { /* 游泳 */ }
public void run() { /* 跑步 */ }
}

合成复用原则 (Composite Reuse Principle)

定义:尽量使用对象组合,而不是继承来达到复用的目的。

示例

1
2
3
4
5
6
7
8
9
10
11
12
// 不好的设计 - 继承复用
class Car extends Engine { }

// 好的设计 - 组合复用
class Engine {
public void start() { }
}
class Car {
private Engine engine;
public Car(Engine engine) { this.engine = engine; }
public void start() { engine.start(); }
}

迪米特法则 (Law of Demeter)

定义:一个对象应该对其他对象保持最少的了解。只与直接的朋友通信。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 不好的设计
class Customer {
public Wallet getWallet() { return wallet; }
}
class Wallet {
public void reduceMoney(int amount) { /* 减少金额 */ }
}
class Store {
public void charge(Customer customer, int amount) {
customer.getWallet().reduceMoney(amount); // 直接操作钱包
}
}

// 好的设计
class Customer {
public void pay(int amount) { wallet.reduceMoney(amount); }
}
class Store {
public void charge(Customer customer, int amount) {
customer.pay(amount); // 只与Customer通信
}
}

创建型模式

单例模式 (Singleton)

定义:确保一个类只有一个实例,并提供一个全局的访问点。

适用场景:数据库连接池、配置管理、日志对象等。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌─────────────────────────────────────────────────┐
│ 请求获取实例 │
└──────────────────┬──────────────────────────────┘


┌─────────────────────────────────────────────────┐
│ 实例是否已存在? │
└──────────────────┬──────────────────────────────┘
┌─────┴─────┐
│ │
是 否
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 返回实例 │ │ 创建实例 │
└─────────────┘ └──────┬──────┘
│ │
└──────┬──────┘


┌─────────────┐
│ 返回实例 │
└─────────────┘

1. 饿汉式 (Eager Initialization)

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private static final Singleton INSTANCE = new Singleton();

private Singleton() {
// 私有构造方法,防止外部实例化
}

public static Singleton getInstance() {
return INSTANCE;
}
}

优缺点

  • 优点:线程安全,实现简单
  • 缺点:类加载时就初始化,浪费内存

2. 懒汉式 (Lazy Initialization)

1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton {
private static Singleton instance;

private Singleton() { }

public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

优缺点

  • 优点:延迟加载,节约资源
  • 缺点:方法加锁,效率低

3. 双重检查锁 (Double-Checked Locking)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Singleton {
private static volatile Singleton instance;

private Singleton() { }

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

关键点

  • volatile 防止指令重排序
  • 双重检查保证线程安全且高效

4. 静态内部类 (Static Inner Class)

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private Singleton() { }

private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

优缺点

  • 优点:线程安全,延迟加载,效率高
  • 缺点:无法传递参数困难

5. 枚举 (Enum)

1
2
3
4
5
6
7
8
9
10
public enum Singleton {
INSTANCE;

public void doSomething() {
// 业务方法
}
}

// 使用
Singleton.INSTANCE.doSomething();

优缺点

  • 优点:最简单,线程安全,防止反射和序列化攻击
  • 缺点:无法继承

面试常见问题

  1. **为什么双重检查锁需要 volatile?

    • 防止 instance = new Singleton() 的指令重排序
  2. **如何防止反射破坏单例?

    • 在构造函数中判断实例已存在则抛出异常
    • 使用枚举实现
  3. 如何防止序列化破坏单例?

    • 实现 readResolve() 方法返回单例
    • 使用枚举

工厂模式

简单工厂模式

定义:由一个工厂类根据传入的参数,动态决定创建哪一个产品类的实例。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
           ┌──────────────┐
│ Client │
└──────┬─────┘


┌──────────────┐
│ Factory │
└──────┬─────┘
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ProductA│ │ProductB│ │ProductC│
└────────┘ └────────┘ └────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface Product {
void use();
}
class ProductA implements Product {
public void use() { System.out.println("使用产品A"); }
}
class ProductB implements Product {
public void use() { System.out.println("使用产品B"); }
}
class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A": return new ProductA();
case "B": return new ProductB();
default: return null;
}
}
}
// 使用
Product product = SimpleFactory.createProduct("A");
product.use();

工厂方法模式

定义:定义一个创建对象的接口,但让子类决定实例化哪一个类。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                ┌──────────────┐
│ Client │
└──────┬─────┘

┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│FactoryA │ │FactoryB │ │FactoryC │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ProductA │ │ProductB │ │ProductC │
└──────────┘ └──────────┘ └──────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface Product {
void use();
}
interface Factory {
Product createProduct();
}
class ProductA implements Product {
public void use() { System.out.println("使用产品A"); }
}
class FactoryA implements Factory {
public Product createProduct() { return new ProductA(); }
}
class ProductB implements Product {
public void use() { System.out.println("使用产品B"); }
}
class FactoryB implements Factory {
public Product createProduct() { return new ProductB(); }
}
// 使用
Factory factory = new FactoryA();
Product product = factory.createProduct();
product.use();

抽象工厂模式

定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 产品族1
interface Button { void click(); }
interface TextField { void input(); }

class WindowsButton implements Button {
public void click() { System.out.println("Windows按钮"); }
}
class WindowsTextField implements TextField {
public void input() { System.out.println("Windows输入框"); }
}
class MacButton implements Button {
public void click() { System.out.println("Mac按钮"); }
}
class MacTextField implements TextField {
public void input() { System.out.println("Mac输入框"); }
}

// 抽象工厂
interface GUIFactory {
Button createButton();
TextField createTextField();
}
class WindowsFactory implements GUIFactory {
public Button createButton() { return new WindowsButton(); }
public TextField createTextField() { return new WindowsTextField(); }
}
class MacFactory implements GUIFactory {
public Button createButton() { return new MacButton(); }
public TextField createTextField() { return new MacTextField(); }
}

// 使用
GUIFactory factory = new WindowsFactory();
Button button = factory.createButton();
TextField textField = factory.createTextField();
button.click();
textField.input();

工厂模式面试常见问题

  1. **简单工厂 vs 工厂方法 vs 抽象工厂的区别?

    • 简单工厂:一个工厂创建所有产品
    • 工厂方法:每个产品对应一个工厂
    • 抽象工厂:创建产品族
  2. Spring框架中如何使用工厂模式?

    • BeanFactory 是工厂模式的典型应用

建造者模式 (Builder)

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
                ┌──────────────┐
│ Director │
└──────┬─────┘

┌──────▼──────┐
│ Builder │
└──────┬─────┘
┌─────────────────┼─────────────────┐
│ │ │
┌────▼─────┐ ┌────▼─────┐ ┌────▼─────┐
│Builder1 │ │Builder2 │ │Builder3 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└─────────────────┼─────────────────┘

┌──────▼──────┐
│ Product │
└──────────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 产品
class Computer {
private String cpu;
private String ram;
private String storage;
private String gpu;

private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.gpu = builder.gpu;
}

public static class Builder {
private String cpu;
private String ram;
private String storage;
private String gpu;

public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder ram(String ram) {
this.ram = ram;
return this;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Builder gpu(String gpu) {
this.gpu = gpu;
return this;
}
public Computer build() {
return new Computer(this);
}
}

@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", storage='" + storage + '\'' +
", gpu='" + gpu + '\'' +
'}';
}
}

// 使用
Computer computer = new Computer.Builder()
.cpu("i9")
.ram("32GB")
.storage("1TB SSD")
.gpu("RTX4090")
.build();
System.out.println(computer);

原型模式 (Prototype)

定义:通过复制现有实例来创建新实例,而不是通过new关键字。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 浅拷贝
class Prototype implements Cloneable {
private String name;
private List<String> list;

public Prototype(String name, List<String> list) {
this.name = name;
this.list = list;
}

@Override
public Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}

// 深拷贝
public Prototype deepClone() {
Prototype copy = new Prototype(this.name, new ArrayList<>(this.list));
return copy;
}
}

结构型模式

适配器模式 (Adapter)

定义:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

流程图

1
2
3
4
5
6
7
8
9
10
11
┌──────────────┐
│ Target │
└──────┬─────┘

┌──────▼──────┐
│ Adapter │
└──────┬─────┘

┌──────▼──────┐
│ Adaptee │
└──────────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 目标接口
interface Target {
void request();
}

// 被适配者
class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}

// 适配器
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}

// 使用
Target target = new Adapter(new Adaptee());
target.request();

装饰器模式 (Decorator)

定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
           ┌──────────────┐
│ Component │
└──────┬─────┘
┌───────────┴───────────┐
│ │
┌────▼─────┐ ┌──────▼──────┐
│Concrete │ │ Decorator │
│Component│ └──────┬─────┘
└──────────┘ │
┌─┴─┐
│ │
┌────▼─────┐
│Concrete │
│Decorator │
└──────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 抽象组件
interface Coffee {
String getDescription();
double getCost();
}

// 具体组件
class SimpleCoffee implements Coffee {
public String getDescription() { return "简单咖啡"; }
public double getCost() { return 10.0; }
}

// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) { this.coffee = coffee; }
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) { super(coffee); }
public String getDescription() { return coffee.getDescription() + ", 加牛奶"; }
public double getCost() { return coffee.getCost() + 2.0; }
}
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) { super(coffee); }
public String getDescription() { return coffee.getDescription() + ", 加糖"; }
public double getCost() { return coffee.getCost() + 1.0; }
}

// 使用
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " = " + coffee.getCost());

代理模式 (Proxy)

定义:为其他对象提供一种代理以控制对这个对象的访问。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
           ┌──────────────┐
│ Subject │
└──────┬─────┘
┌───────────┴───────────┐
│ │
┌────▼─────┐ ┌──────▼──────┐
│ Real │ │ Proxy │
│ Subject │ └──────┬─────┘
└──────────┘ │

┌──────────┴──────────┐
│ │
┌────▼─────┐ ┌──────▼──────┐
│ 控制访问 │ │ 调用真实 │
└──────────┘ │ 对象 │
└──────────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 主题接口
interface Image {
void display();
}

// 真实主题
class RealImage implements Image {
private String fileName;

public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}

private void loadFromDisk() {
System.out.println("加载 " + fileName);
}

public void display() {
System.out.println("显示 " + fileName);
}
}

// 代理
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;

public ProxyImage(String fileName) {
this.fileName = fileName;
}

public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}

// 使用
Image image = new ProxyImage("test.jpg");
image.display(); // 第一次加载并显示
image.display(); // 直接显示

外观模式 (Facade)

定义:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 子系统
class CPU {
public void start() { System.out.println("CPU启动"); }
}
class Memory {
public void load() { System.out.println("内存加载"); }
}
class Disk {
public void read() { System.out.println("磁盘读取"); }
}

// 外观类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private Disk disk;

public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.disk = new Disk();
}

public void start() {
cpu.start();
memory.load();
disk.read();
System.out.println("电脑启动完成");
}
}

// 使用
ComputerFacade computer = new ComputerFacade();
computer.start();

桥接模式 (Bridge)

定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 实现部分接口
interface Color {
String getColor();
}
class Red implements Color {
public String getColor() { return "红色"; }
}
class Blue implements Color {
public String getColor() { return "蓝色"; }
}

// 抽象部分
abstract class Shape {
protected Color color;
public Shape(Color color) { this.color = color; }
public abstract void draw();
}
class Circle extends Shape {
public Circle(Color color) { super(color); }
public void draw() {
System.out.println("画一个" + color.getColor() + "圆");
}
}
class Square extends Shape {
public Square(Color color) { super(color); }
public void draw() {
System.out.println("画一个" + color.getColor() + "正方形");
}
}

// 使用
Color red = new Red();
Shape redCircle = new Circle(red);
redCircle.draw();

组合模式 (Composite)

定义:将对象组合成树形结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.util.ArrayList;
import java.util.List;

abstract class Component {
protected String name;
public Component(String name) { this.name = name; }
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract void display(int depth);
}

class Leaf extends Component {
public Leaf(String name) { super(name); }
public void add(Component component) {
System.out.println("叶子节点不能添加");
}
public void remove(Component component) {
System.out.println("叶子节点不能删除");
}
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println(name);
}
}

class Composite extends Component {
private List<Component> children = new ArrayList<>();
public Composite(String name) { super(name); }
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println(name);
for (Component component : children) {
component.display(depth + 2);
}
}
}

// 使用
Composite root = new Composite("根目录");
root.add(new Leaf("文件1.txt"));
Composite dir1 = new Composite("文件夹1");
dir1.add(new Leaf("文件2.txt"));
root.add(dir1);
root.display(0);

行为型模式

策略模式 (Strategy)

定义:定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
                ┌──────────────┐
│ Context │
└──────┬─────┘

┌──────▼──────┐
│ Strategy │
└──────┬─────┘
┌─────────────────┼─────────────────┐
│ │ │
┌────▼─────┐ ┌────▼─────┐ ┌────▼─────┐
│Strategy1 │ │Strategy2 │ │Strategy3 │
└──────────┘ └──────────┘ └──────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 策略接口
interface PaymentStrategy {
void pay(double amount);
}

class AliPayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("支付宝支付: " + amount);
}
}
class WeChatPayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("微信支付: " + amount);
}
}
class CreditCardStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("信用卡支付: " + amount);
}
}

// 上下文
class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(double amount) {
strategy.pay(amount);
}
}

// 使用
PaymentContext context = new PaymentContext(new AliPayStrategy());
context.executePayment(100.0);

观察者模式 (Observer)

定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                ┌──────────────┐
│ Subject │
└──────┬─────┘
┌───────────┴───────────┐
│ │
┌────▼─────┐ ┌──────▼──────┐
│ attach() │ │ detach() │
│ notify() │ └──────────────┘
└────┬─────┘

┌────┴─────┐
│ │
┌────▼─────┐ ┌────▼─────┐
│ Observer1 │ │ Observer2 │
└──────────┘ └──────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.util.ArrayList;
import java.util.List;

// 主题
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}

// 观察者
interface Observer {
void update(String message);
}

// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;

public void setState(String state) {
this.state = state;
notifyObservers();
}

public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}

// 具体观察者
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " 收到消息: " + message);
}
}

// 使用
Subject subject = new ConcreteSubject();
subject.attach(new ConcreteObserver("观察者1"));
subject.attach(new ConcreteObserver("观察者2"));
((ConcreteSubject) subject).setState("状态更新");

模板方法模式 (Template Method)

定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
           ┌─────────────────────────┐
│ AbstractClass │
│ ───────────── │
│ + templateMethod() │
│ - primitive1() │
│ - primitive2() │
└───────────┬─────────────┘

┌───────────┴─────────────┐
│ │
┌──────────▼──────────┐ ┌──────────▼──────────┐
│ ConcreteClass1 │ │ ConcreteClass2 │
│ ─────────────── │ │ ─────────────── │
│ - primitive1() │ │ - primitive1() │
│ - primitive2() │ │ - primitive2() │
└───────────────────────┘ └───────────────────────┘

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 抽象类
abstract class BankTemplate {
// 模板方法
public final void processBusiness() {
takeNumber();
transact();
evaluate();
}

// 具体方法 - 取号
protected void takeNumber() {
System.out.println("取号排队");
}

// 抽象方法 - 办理具体业务,子类实现
protected abstract void transact();

// 具体方法 - 评价
protected void evaluate() {
System.out.println("服务评价");
}
}

// 具体子类
class DepositBusiness extends BankTemplate {
protected void transact() {
System.out.println("办理存款业务");
}
}
class WithdrawBusiness extends BankTemplate {
protected void transact() {
System.out.println("办理取款业务");
}
}

// 使用
BankTemplate business = new DepositBusiness();
business.processBusiness();

责任链模式 (Chain of Responsibility)

定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 处理者
abstract class Handler {
protected Handler nextHandler;

public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}

public abstract void handleRequest(int request);
}

class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request < 10) {
System.out.println("HandlerA处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandlerB extends Handler {
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println("HandlerB处理请求: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}

// 使用
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNextHandler(handlerB);
handlerA.handleRequest(5);
handlerA.handleRequest(15);

命令模式 (Command)

定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 命令接口
interface Command {
void execute();
void undo();
}

// 接收者
class Light {
public void on() { System.out.println("灯打开了"); }
public void off() { System.out.println("灯关上了"); }
}

// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
public void execute() { light.on(); }
public void undo() { light.off(); }
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) { this.light = light; }
public void execute() { light.off(); }
public void undo() { light.on(); }
}

// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) { this.command = command; }
public void pressButton() { command.execute(); }
public void pressUndo() { command.undo(); }
}

// 使用
Light light = new Light();
Command onCommand = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(onCommand);
remote.pressButton();
remote.pressUndo();

状态模式 (State)

定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 状态接口
interface State {
void handle(Context context);
}

// 上下文
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}

// 具体状态
class ConcreteStateA implements State {
public void handle(Context context) {
System.out.println("当前状态是A,切换到B");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB implements State {
public void handle(Context context) {
System.out.println("当前状态是B,切换到A");
context.setState(new ConcreteStateA());
}
}

// 使用
Context context = new Context();
context.setState(new ConcreteStateA());
context.request();
context.request();

迭代器模式 (Iterator)

定义:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.ArrayList;
import java.util.List;

// 迭代器接口
interface Iterator<T> {
boolean hasNext();
T next();
}

// 聚合接口
interface Aggregate<T> {
Iterator<T> createIterator();
}

// 具体聚合
class ConcreteAggregate<T> implements Aggregate<T> {
private List<T> items = new ArrayList<>();
public void add(T item) { items.add(item); }
public T get(int index) { return items.get(index); }
public int size() { return items.size(); }
public Iterator<T> createIterator() {
return new ConcreteIterator<>(this);
}
}

// 具体迭代器
class ConcreteIterator<T> implements Iterator<T> {
private ConcreteAggregate<T> aggregate;
private int index = 0;
public ConcreteIterator(ConcreteAggregate<T> aggregate) {
this.aggregate = aggregate;
}
public boolean hasNext() {
return index < aggregate.size();
}
public T next() {
return aggregate.get(index++);
}
}

// 使用
ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
aggregate.add("A");
aggregate.add("B");
aggregate.add("C");
Iterator<String> iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}

设计模式面试总结

常见面试问题

  1. **设计模式的六大原则是什么?

    • 单一职责、开闭原则、里氏替换、依赖倒转、接口隔离、迪米特法则
  2. **单例模式的几种实现方式及其优缺点?

    • 饿汉式、懒汉式、双重检查锁、静态内部类、枚举
  3. **工厂模式三种形态的区别?

    • 简单工厂、工厂方法、抽象工厂
  4. **代理模式和装饰器模式的区别?

    • 代理模式强调控制访问,装饰器模式强调增强功能
  5. **Spring中使用了哪些设计模式?

    • 单例模式、工厂模式、代理模式、模板方法、观察者等
  6. **JDK中使用了哪些设计模式?

    • 适配器模式(InputStreamReader)
    • 装饰器模式(IO流)
    • 单例模式(Runtime)
    • 迭代器模式(Iterator)

设计模式选择建议

问题场景推荐模式
需要唯一实例单例模式
创建复杂对象建造者模式
需灵活创建对象工厂模式
需动态增加功能装饰器模式
需控制对象访问代理模式
需简化子系统接口外观模式
算法需灵活切换策略模式
一对多通知观察者模式
算法骨架固定,步骤变化模板方法