Skip to content

几种常用的设计模式

设计模式是软件开发领域中总结出的通用解决方案,用于解决在特定环境下经常遇到的设计问题。 它们并不是具体的代码实现,而是描述了解决某类问题的抽象思想和可复用的设计模板。 在软件开发中,设计模式帮助开发人员实现代码的可读性、扩展性和复用性,同时促进团队成员之间的高效沟通。

单例模式

单例模式(Singleton Pattern)是一种创建型设计模式,目的是确保一个类在系统中只有一个实例,并提供一个全局访问点。单例模式常被用于表示全局唯一的资源或对象,例如配置管理器、日志系统、线程池等。

Java
package com.practice.patterns;

public class Singleton {
    private static volatile Singleton instance = null;

    private Singleton() {

    }

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

关键点:

  • 使用 volatile 修饰符确保多线程环境中对变量的修改对所有线程立即可见,避免指令重排序问题。
  • 私有化构造方法,禁止外部直接创建实例。
  • 通过 getInstance() 获取唯一实例,确保一个类只有一个实例,并提供全局访问点。
  • 双重检查锁定,第一次检查 instance 是否为 null,避免不必要的同步。进入同步块后再检查一次,以确保线程安全。
  • 使用 synchronized 关键字,保证同一时间只有一个线程能执行实例化代码。

工厂模式

工厂模式(Factory Pattern)是一种创建型设计模式,其目的是通过定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂模式将对象的创建逻辑与使用逻辑分离,使得代码更加灵活和可维护。

定义一个接口或抽象类 Shape,描述所有具体对象的公共行为。

Java
package com.practice.service;

public interface Shape {
    void draw();
}

具体实现类 Circle 实现接口 Shape,提供具体行为。

Java
package com.practice.service.impl;

import com.practice.service.Shape;

public class Circle implements Shape {
    public void draw() {
        System.out.println("画一个圆");
    }
}

具体实现类 Rectangle 实现接口 Shape,提供具体行为。

Java
package com.practice.service.impl;

import com.practice.service.Shape;

public class Rectangle implements Shape {
    public void draw() {
        System.out.println("画一个长方形");
    }
}

ShapeFactory 是工厂类,根据参数 shapeType 动态返回具体对象。

Java
package com.practice.patterns;

import com.practice.service.Shape;
import com.practice.service.impl.Circle;
import com.practice.service.impl.Rectangle;

public class ShapeFactory {
    public static Shape getShape(String shapeType) {
        if ("CIRCLE".equalsIgnoreCase(shapeType)) {
            return new Circle();
        } else if ("RECTANGLE".equalsIgnoreCase(shapeType)) {
            return new Rectangle();
        }
        return null;
    }
}

通过工厂获取对象,无需关心对象的具体实现细节。

Java
package com.practice.app;

import com.practice.patterns.ShapeFactory;
import com.practice.service.Shape;

public class FactoryPatternDemo {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("CIRCLE");
        circle.draw();
        // 输出:画一个圆

        Shape rectangle = ShapeFactory.getShape("RECTANGLE");
        rectangle.draw();
        // 输出:画一个长方形
    }
}

关键点:

  • 解耦了对象的创建与使用。
  • 更容易扩展,添加新类型时,只需修改工厂代码。

观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会收到通知并自动更新。

定义观察者接口,强制实现 update 方法,用于接收通知。

Java
package com.practice.service;

public interface Observer {
    void update(String message);
}

实现观察者接口

Java
package com.practice.service.impl;

import com.practice.service.Observer;

public class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + " received: " + message);
    }
}

Subject 类维护一个观察者列表,通过 addObserverremoveObserver 方法管理观察者。
调用 notifyObservers 通知所有观察者。

Java
package com.practice.common;

import com.practice.service.Observer;

import java.util.ArrayList;
import java.util.List;

public class Subject {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

动态注册观察者。
当状态变化时,所有观察者都会收到通知。

Java
package com.practice.app;

import com.practice.common.Subject;
import com.practice.service.Observer;
import com.practice.service.impl.ConcreteObserver;

public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();

        Observer observer1 = new ConcreteObserver("Observer1");
        Observer observer2 = new ConcreteObserver("Observer2");

        subject.addObserver(observer1);
        subject.addObserver(observer2);

        subject.notifyObservers("Event 1 occurred!");
        subject.notifyObservers("Event 2 occurred!");

        // 输出
        // Observer1 received: Event 1 occurred!
        // Observer2 received: Event 1 occurred!
        // Observer1 received: Event 2 occurred!
        // Observer2 received: Event 2 occurred!
    }
}

关键点:

  • 实现松耦合,Subject 不需要直接依赖具体的观察者实现。
  • 常用于事件驱动的系统,如 GUI 事件系统、数据模型更新、实时消息系统。

策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,定义了一系列算法,将每种算法封装到独立的类中,并使它们可以互相替换。这种模式使得算法可以在不影响客户端的情况下发生变化,从而满足开闭原则。

定义策略接口,包含一个行为方法 execute

Java
package com.practice.service;

public interface Strategy {
    int execute(int a, int b);
}

实现策略接口,提供求和算法实现。

Java
package com.practice.service.impl;

import com.practice.service.Strategy;

public class AdditionStrategy implements Strategy {
    public int execute(int a, int b) {
        return a + b;
    }
}

实现策略接口,提供乘法算法实现。

Java
package com.practice.service.impl;

import com.practice.service.Strategy;

public class MultiplicationStrategy implements Strategy {
    public int execute(int a, int b) {
        return a * b;
    }
}

StrategyContext 类持有策略引用,动态调用具体策略实现。

Java
package com.practice.common;

import com.practice.service.Strategy;

public class StrategyContext {
    private Strategy strategy;

    public StrategyContext(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }
}

动态切换策略,无需修改已有代码。

Java
package com.practice.app;

import com.practice.common.StrategyContext;
import com.practice.service.impl.AdditionStrategy;
import com.practice.service.impl.MultiplicationStrategy;

public class StrategyPatternDemo {
    public static void main(String[] args) {
        StrategyContext context = new StrategyContext(new AdditionStrategy());
        System.out.println("加法计算结果: " + context.executeStrategy(5, 3));
        // 输出:加法计算结果: 8

        context.setStrategy(new MultiplicationStrategy());
        System.out.println("乘法计算结果: " + context.executeStrategy(5, 3));
        // 输出:乘法计算结果: 15
    }
}

关键点:

  • 策略模式封装了算法,使得算法可以互换。
  • 客户端代码与算法解耦,便于扩展新的算法。

装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,用于在不修改现有类的情况下动态地为对象添加新的功能。通过将对象嵌套在装饰器中,可以以类似于递归的方式叠加多个功能。

定义组件接口,描述核心功能。

Java
package com.practice.service;

public interface Component {
    void operation();
}

实现组件接口,提供基本功能。

Java
package com.practice.service.impl;

import com.practice.service.Component;

public class ConcreteComponent implements Component {
    public void operation() {
        System.out.println("基本功能");
    }
}

抽象装饰器类持有组件引用,通过组合实现扩展。

Java
package com.practice.patterns;

import com.practice.service.Component;

public abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

具体装饰器实现附加功能A,通过调用父类方法保留原有功能。

Java
package com.practice.common;

import com.practice.patterns.Decorator;
import com.practice.service.Component;

public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        System.out.println("添加的功能 A");
    }
}

具体装饰器实现附加功能B,通过调用父类方法保留原有功能。

Java
package com.practice.common;

import com.practice.patterns.Decorator;
import com.practice.service.Component;

public class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        System.out.println("添加的功能 B");
    }
}

自由组合装饰器,动态添加功能。

Java
package com.practice.app;

import com.practice.common.ConcreteDecoratorA;
import com.practice.common.ConcreteDecoratorB;
import com.practice.service.Component;
import com.practice.service.impl.ConcreteComponent;

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component decoratorA = new ConcreteDecoratorA(component);
        Component decoratorB = new ConcreteDecoratorB(decoratorA);

        decoratorB.operation();
        // 输出
        // 基本功能
        // 添加的功能 A
        // 添加的功能 B
    }
}

关键点:

  • 动态为对象添加职责,而不是通过继承。
  • 提高了系统的灵活性和可扩展性。

适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,用于将一个接口转换成客户端期望的另一个接口。适配器模式让原本不兼容的类可以协同工作。

目标接口:定义客户端期望使用的接口,假设新需求是播放 MP4

Java
package com.practice.service;

public interface MediaPlayer {
    void request();
}

被适配者:已有的类,只支持播放 mp3

Java
package com.practice.common;

public class Mp3Player {
    public void playMp3(String fileName) {
        System.out.println("播放 mp3 文件: " + fileName);
    }
}

适配器:将 MediaPlayer 转换为 Mp3Player 的接口

Java
package com.practice.service.impl;

import com.practice.common.Mp3Player;
import com.practice.service.MediaPlayer;

public class MediaAdapter implements MediaPlayer {
    private Mp3Player mp3Player;

    public MediaAdapter() {
        this.mp3Player = new Mp3Player();
    }

    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("mp3")) {
            mp3Player.playMp3(fileName);
        } else {
            System.out.println("无效的音频类型: " + audioType);
        }
    }
}

客户端类:使用 MediaPlayer 播放音频

Java
package com.practice.service.impl;

import com.practice.service.MediaPlayer;

public class AudioPlayer implements MediaPlayer {
    private MediaAdapter mediaAdapter;

    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("mp3")) {
            System.out.println("立即播放 mp3 文件: " + fileName);
        } else if (audioType.equalsIgnoreCase("mp4")) {
            mediaAdapter = new MediaAdapter();
            mediaAdapter.play(audioType, fileName);
        } else {
            System.out.println("不支持的音频类型: " + audioType);
        }
    }
}

测试代码

Java
package com.practice.app;

import com.practice.service.impl.AudioPlayer;

public class AdapterPatternDemo {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();

        audioPlayer.play("mp3", "音乐.mp3");
        audioPlayer.play("mp4", "视频.mp4");
        audioPlayer.play("wav", "音频.wav");
        // 输出
        // 立即播放 mp3 文件: 音乐.mp3
        // 无效的音频类型: mp4
        // 不支持的音频类型: wav
    }
}

关键点:

  • 兼容性。
  • 解耦。
  • 扩展性。

总结与选择指南

在实际开发中,选择合适的设计模式可以事半功倍。以下是常用模式的快速选择指南:

设计模式核心思想适用场景举例
单例模式 (Singleton)确保唯一全局只需要一个实例,如配置、日志、连接池Runtime, Spring Bean (默认)
工厂模式 (Factory)解耦创建对象创建复杂,或需要根据条件创建不同对象BeanFactory, Calendar.getInstance()
观察者模式 (Observer)事件驱动一个对象变化需通知多个对象,解耦触发与响应Vue 响应式, EventBus, 消息队列
策略模式 (Strategy)算法互换同一任务有多种算法,需要在运行时动态切换支付方式(阿里/微信), 排序算法
装饰器模式 (Decorator)动态增强不修改原类代码,动态添加功能,避免类爆炸IO流 (BufferedInputStream), 咖啡加糖
适配器模式 (Adapter)接口转换接口不兼容,需要复用旧代码或协同工作Arrays.asList(), 电源适配器

快速判断口诀

  • 全局唯一 找单例
  • 对象复杂 找工厂
  • 多方通知 找观察
  • 算法切换 找策略
  • 功能增强 找装饰
  • 接口兼容 找适配

最后更新: