Java 设计模式详解:从入门到实践
在软件开发中,设计模式(Design Patterns) 是解决常见问题的经典解决方案。它们不是具体的代码库或框架,而是经过验证的设计思想和模板,帮助我们编写更灵活、可维护、可扩展的代码。
Java 作为一门面向对象的语言,非常适合应用设计模式。本文将带你全面了解 23 种经典 GoF(Gang of Four)设计模式,并结合 Java 示例进行讲解。
一、什么是设计模式?
设计模式 = 问题 + 解决方案 + 场景
它由四位作者在《Design Patterns: Elements of Reusable Object-Oriented Software》一书中提出,总结了面向对象设计中的最佳实践。
设计模式的三要素:
- 模式名称(Pattern Name):便于交流。
- 问题(Problem):在什么情况下使用该模式?
- 解决方案(Solution):如何实现?类结构是怎样的?
- 后果(Consequences):带来的好处与代价。
使用设计模式的好处:
- 提高代码复用性
- 增强系统的可维护性和可扩展性
- 降低模块间的耦合度
- 提升团队沟通效率(有“共同语言”)
二、设计模式的三大分类
根据用途,设计模式分为三大类,共 23 种:
| 类别 | 模式数量 | 主要目的 |
|---|---|---|
| 创建型(Creational) | 5 种 | 控制对象的创建过程 |
| 结构型(Structural) | 7 种 | 组合类或对象形成更大结构 |
| 行为型(Behavioral) | 11 种 | 定义对象间通信方式 |
下面我们逐一详解。
三、创建型模式(Creational Patterns)
这类模式关注如何创建对象,而不是直接使用 new 关键字,从而提高灵活性。
1. 单例模式(Singleton Pattern)
作用:确保一个类只有一个实例,并提供全局访问点。
适用场景:
- 配置管理器
- 日志记录器
- 线程池、连接池
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保证线程安全。
2. 工厂方法模式(Factory Method Pattern)
作用:定义一个创建对象的接口,但让子类决定实例化哪个类。
interface Product {
void use();
}
class ConcreteProductA implements Product {
public void use() { System.out.println("使用产品A"); }
}
class ConcreteProductB implements Product {
public void use() { System.out.println("使用产品B"); }
}
abstract class Factory {
public abstract Product createProduct();
public void doWork() {
Product p = createProduct();
p.use();
}
}
class ConcreteFactoryA extends Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
优点:符合开闭原则,新增产品无需修改工厂逻辑。
3. 抽象工厂模式(Abstract Factory Pattern)
作用:创建一系列相关或依赖对象的接口,而无需指定具体类。
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
interface Button { void render(); }
interface Checkbox { void select(); }
class WinButton implements Button {
public void render() { System.out.println("渲染Windows按钮"); }
}
class MacButton implements Button {
public void render() { System.out.println("渲染Mac按钮"); }
}
class WinFactory implements GUIFactory {
public Button createButton() { return new WinButton(); }
public Checkbox createCheckbox() { return new WinCheckbox(); }
}
适用场景:跨平台 UI 组件库、主题系统。
4. 建造者模式(Builder Pattern)
作用:将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
class Computer {
private String cpu;
private String ram;
private String storage;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
}
public static class Builder {
private String cpu, ram, storage;
public Builder setCpu(String cpu) { this.cpu = cpu; return this; }
public Builder setRam(String ram) { this.ram = ram; return this; }
public Builder setStorage(String storage) { this.storage = storage; return this; }
public Computer build() { return new Computer(this); }
}
}
// 使用
Computer pc = new Computer.Builder()
.setCpu("i7")
.setRam("16GB")
.setStorage("512GB SSD")
.build();
优点:避免构造函数参数过多,提升可读性。
5. 原型模式(Prototype Pattern)
作用:通过复制现有对象来创建新对象,而不是通过 new 创建。
class Prototype implements Cloneable {
private String data;
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
适用场景:对象初始化成本高、需要动态配置时。
四、结构型模式(Structural Patterns)
这类模式关注类和对象的组合,形成更大的结构。
6. 适配器模式(Adapter Pattern)
作用:将一个类的接口转换成客户期望的另一个接口。
class EuropeanSocket {
public void providePower() {
System.out.println("提供220V电源");
}
}
interface USSocket {
void plugIn();
}
class SocketAdapter implements USSocket {
private EuropeanSocket socket;
public SocketAdapter(EuropeanSocket socket) {
this.socket = socket;
}
public void plugIn() {
System.out.print("转换电压 -> ");
socket.providePower();
}
}
适用场景:集成第三方库、旧系统迁移。
7. 装饰器模式(Decorator Pattern)
作用:动态地给对象添加功能,而不改变其结构。
interface Coffee {
String getDescription();
double cost();
}
class SimpleCoffee implements Coffee {
public String getDescription() { return "咖啡"; }
public double cost() { return 2.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 cost() {
return coffee.cost() + 0.5;
}
}
// 使用
Coffee c = new MilkDecorator(new SimpleCoffee());
System.out.println(c.getDescription() + ": $" + c.cost()); // 咖啡, 牛奶: $2.5
优点:替代继承,避免类爆炸。
8. 代理模式(Proxy Pattern)
作用:为其他对象提供一种代理以控制对这个对象的访问。
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 String filename;
private RealImage realImage;
public ProxyImage(String filename) {
this.filename = filename;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
应用场景:懒加载、权限控制、日志记录、远程调用(RMI)。
9. 外观模式(Facade Pattern)
作用:为子系统提供一个统一的接口,简化客户端调用。
class CPU {
public void freeze() { System.out.println("CPU 冻结"); }
public void jump(long position) { System.out.println("跳转到地址: " + position); }
public void execute() { System.out.println("执行指令"); }
}
class Memory {
public void load(long position, byte[] data) {
System.out.println("内存加载数据");
}
}
class HardDrive {
public byte[] read(long lba, int size) {
System.out.println("硬盘读取数据");
return new byte[1024];
}
}
class ComputerFacade {
private CPU cpu = new CPU();
private Memory memory = new Memory();
private HardDrive hd = new HardDrive();
public void start() {
cpu.freeze();
byte[] data = hd.read(0, 1024);
memory.load(0, data);
cpu.jump(0);
cpu.execute();
}
}
// 客户端只需调用
new ComputerFacade().start();
优点:解耦复杂系统,降低使用门槛。
10. 桥接模式(Bridge Pattern)
作用:将抽象部分与实现部分分离,使它们可以独立变化。
interface Color {
void applyColor();
}
class Red implements Color {
public void applyColor() { System.out.println("红色"); }
}
abstract class Shape {
protected Color color;
public Shape(Color color) {
this.color = color;
}
abstract void draw();
}
class Circle extends Shape {
public Circle(Color color) { super(color); }
public void draw() {
System.out.print("圆形 - ");
color.applyColor();
}
}
优点:避免类层次结构爆炸,支持多维度扩展。
11. 组合模式(Composite Pattern)
作用:将对象组合成树形结构以表示“部分-整体”的层次结构。
import java.util.*;
abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
public abstract void operation();
}
class Leaf extends Component {
public Leaf(String name) { super(name); }
public void operation() {
System.out.println("叶子节点: " + name);
}
}
class Composite extends Component {
private List<Component> children = new ArrayList<>();
public Composite(String name) { super(name); }
public void add(Component c) {
children.add(c);
}
public void remove(Component c) {
children.remove(c);
}
public void operation() {
System.out.println("容器节点: " + name);
for (Component child : children) {
child.operation();
}
}
}
适用场景:文件系统、菜单树、组织架构图。
12. 享元模式(Flyweight Pattern)
作用:共享细粒度对象,减少内存使用。
class CharacterFlyweight {
private char character;
private String font;
private int size;
public CharacterFlyweight(char character, String font, int size) {
this.character = character;
this.font = font;
this.size = size;
}
public void display(int x, int y) {
System.out.println("显示字符 '" + character + "' at (" + x + "," + y + ")");
}
}
class FlyweightFactory {
private Map<String, CharacterFlyweight> pool = new HashMap<>();
public CharacterFlyweight get(char c, String font, int size) {
String key = c + "-" + font + "-" + size;
return pool.computeIfAbsent(key, k ->
new CharacterFlyweight(c, font, size));
}
}
适用场景:文本编辑器、大量相似对象的系统。
五、行为型模式(Behavioral Patterns)
这类模式关注对象之间的职责分配和通信机制。
13. 策略模式(Strategy Pattern)
作用:定义一系列算法,封装每个算法,并使它们可互换。
interface PaymentStrategy {
void pay(int amount);
}
class CreditCardPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("使用信用卡支付: " + amount);
}
}
class WeChatPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("使用微信支付: " + amount);
}
}
class ShoppingCart {
private PaymentStrategy strategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void checkout(int amount) {
strategy.pay(amount);
}
}
优点:消除条件判断,易于扩展新策略。
14. 观察者模式(Observer Pattern)
作用:定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者自动更新。
import java.util.*;
interface Observer {
void update(String message);
}
class User implements Observer {
private String name;
public User(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " 收到通知: " + message);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer o) {
observers.add(o);
}
public void notifyObservers(String msg) {
for (Observer o : observers) {
o.update(msg);
}
}
}
// 使用
Subject subject = new Subject();
subject.addObserver(new User("Alice"));
subject.addObserver(new User("Bob"));
subject.notifyObservers("系统更新啦!");
应用场景:事件监听、消息订阅、MVC 模式中的视图更新。
15. 责任链模式(Chain of Responsibility)
作用:将请求沿处理链传递,直到某个对象处理它。
abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handle(Request request);
}
class Request {
private String type;
public Request(String type) { this.type = type; }
public String getType() { return type; }
}
class AuthHandler extends Handler {
public void handle(Request request) {
System.out.println("认证检查...");
if (next != null) next.handle(request);
}
}
class LoggingHandler extends Handler {
public void handle(Request request) {
System.out.println("记录日志...");
if (next != null) next.handle(request);
}
}
// 使用
Handler chain = new AuthHandler();
chain.setNext(new LoggingHandler());
chain.handle(new Request("login"));
优点:解耦发送者与接收者,支持动态组合处理流程。
16. 命令模式(Command Pattern)
作用:将请求封装为对象,使其可以参数化、队列化、撤销等。
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 RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
应用场景:GUI 按钮、事务操作、宏命令、撤销/重做功能。
17. 状态模式(State Pattern)
作用:允许对象在其内部状态改变时改变其行为。
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");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB implements State {
public void handle(Context context) {
System.out.println("处于状态B");
context.setState(new ConcreteStateA());
}
}
优点:避免大量 if-else 判断状态转移。
18. 模板方法模式(Template Method Pattern)
作用:定义算法骨架,将某些步骤延迟到子类实现。
abstract class GameTemplate {
public final void play() {
initialize();
startPlay();
endPlay();
}
abstract void initialize();
abstract void startPlay();
void endPlay() {
System.out.println("游戏结束");
}
}
class Cricket extends GameTemplate {
void initialize() { System.out.println("初始化棒球游戏"); }
void startPlay() { System.out.println("开始打棒球"); }
}
应用场景:框架设计(如 Spring 中的 JdbcTemplate)。
19. 访问者模式(Visitor Pattern)
作用:在不修改类的前提下,为类增加新的操作。
interface Element {
void accept(Visitor visitor);
}
interface Visitor {
void visit(Book book);
void visit(DVD dvd);
}
class Book implements Element {
private double price;
public Book(double price) { this.price = price; }
public double getPrice() { return price; }
public void accept(Visitor visitor) { visitor.visit(this); }
}
class TaxVisitor implements Visitor {
public void visit(Book book) {
System.out.println("图书税费: " + book.getPrice() * 0.05);
}
public void visit(DVD dvd) {
System.out.println("DVD税费: " + dvd.getPrice() * 0.1);
}
}
适用场景:报表生成、数据导出、多种操作需要遍历同一结构。
20. 中介者模式(Mediator Pattern)
作用:用一个中介对象封装一系列对象之间的交互。
interface Mediator {
void sendMessage(String msg, Colleague colleague);
}
abstract class Colleague {
protected Mediator mediator;
protected String name;
public Colleague(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void receive(String msg);
public abstract void send(String msg);
}
class ChatRoom implements Mediator {
public void sendMessage(String msg, Colleague colleague) {
System.out.println(colleague.name + " 发送: " + msg);
}
}
优点:减少对象间的直接依赖,集中管理交互逻辑。
21. 备忘录模式(Memento Pattern)
作用:在不破坏封装性的前提下,捕获并外部化一个对象的内部状态,以便以后恢复。
class Memento {
private String state;
public Memento(String state) { this.state = state; }
public String getState() { return state; }
}
class Originator {
private String state;
public void setState(String state) { this.state = state; }
public Memento saveState() { return new Memento(state); }
public void restoreState(Memento m) { this.state = m.getState(); }
}
class Caretaker {
private Stack<Memento> history = new Stack<>();
public void push(Memento m) { history.push(m); }
public Memento pop() { return history.pop(); }
}
应用场景:撤销功能、快照机制。
22. 迭代器模式(Iterator Pattern)
作用:提供一种方法顺序访问聚合对象中的各个元素,而又不暴露其内部表示。
interface Iterator<T> {
boolean hasNext();
T next();
}
interface Collection<T> {
Iterator<T> createIterator();
}
class MyList<T> implements Collection<T> {
private List<T> items = new ArrayList<>();
public void add(T item) { items.add(item); }
public Iterator<T> createIterator() {
return new ListIterator<>(items);
}
}
class ListIterator<T> implements Iterator<T> {
private List<T> items;
private int index = 0;
public ListIterator(List<T> items) { this.items = items; }
public boolean hasNext() { return index < items.size(); }
public T next() { return items.get(index++); }
}
Java 中的 Iterator 接口就是典型的实现。
23. 解释器模式(Interpreter Pattern)
作用:定义语言的文法,并解释执行句子。
interface Expression {
boolean interpret(String context);
}
class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) { this.data = data; }
public boolean interpret(String context) {
return context.contains(data);
}
}
适用场景:简单规则引擎、正则表达式解析(较少使用,因性能较低)。
六、总结:如何选择合适的设计模式?
| 问题 | 推荐模式 |
|---|---|
| 只想创建一个实例 | 单例模式 |
| 对象创建逻辑复杂 | 工厂 / 建造者 |
| 需要动态添加功能 | 装饰器 |
| 多种算法可切换 | 策略 |
| 对象状态频繁变化 | 状态 |
| 发布-订阅机制 | 观察者 |
| 请求处理流程长 | 责任链 |
| 避免紧耦合 | 适配器 / 中介者 / 门面 |
💡 设计模式不是银弹,过度使用会导致代码复杂化。应遵循:
- KISS 原则(Keep It Simple, Stupid)
- YAGNI 原则(You Aren’t Gonna Need It)
- 先写好代码,再考虑是否需要重构为模式
参考资料
- 《设计模式:可复用面向对象软件的基础》——GoF
- 《Head First 设计模式》——易懂入门书
- Refactoring Guru 网站
- JDK 源码中的设计模式(如
java.util.Collections使用装饰器)
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨
所有评论(0)