设计模式

35 阅读23分钟

第一部分 设计模式与设计原则

设计模式概述

创建型模式(Creational Patterns)
  • 工厂模式(Factory):通过工厂类统一创建对象,隐藏实例化细节
  • 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点
  • 建造者模式(Builder):分步骤构建复杂对象,分离构造过程与表示
  • 原型模式(Prototype):通过克隆已有对象创建新对象,避免重复初始化
结构型模式(Structural Patterns)
  • 适配器模式(Adapter):兼容不兼容接口,使类协同工作
  • 装饰器模式(Decorator):动态地为对象添加职责,避免继承爆炸
  • 代理模式(Proxy):为对象提供代理,控制对原对象的访问(如延迟加载、权限控制)
  • 组合模式(Composite):以树形结构处理整体-部分关系,统一对待单个对象和组合对象
行为型模式(Behavioral Patterns)
  • 观察者模式(Observer):定义对象间的一对多依赖,当一个对象状态改变时,自动通知依赖对象
  • 策略模式(Strategy):定义算法族,封装每个算法,使其可互相替换
  • 责任链模式(Chain of Responsibility):将请求的发送者与接收者解耦,允许多个对象处理请求
  • 模板方法模式(Template Method):定义算法骨架,将某些步骤延迟到子类实现

面向对象设计原则

单一职责原则(SRP, Single Responsibility Principle)
  • 定义:一个类(或模块、方法)应该只有一个引起它变化的原因,即只承担一种职责
  • 核心思想:通过职责分离,降低类的复杂度,避免修改一处代码影响多个功能
  • 应用场景:当类的方法明显属于不同领域(如业务逻辑、数据持久化、日志记录)时;避免“上帝类”,即一个类实现过多功能
开闭原则(OCP, Open-Closed Principle)
  • 定义:软件实体(类、模块、函数)应对扩展开放,对修改关闭
  • 核心思想:通过抽象和继承/组合,允许在不修改现有代码的情况下扩展功能
  • 应用场景:功能需要频繁扩展(如支付方式、日志输出类型);使用策略模式、工厂模式等实现OCP
里氏替换原则(LSP, Liskov Substitution Principle)
  • 定义:子类必须能够替换其父类,且替换后程序的行为不变
  • 核心思想:继承关系应基于行为的一致性,而非单纯复用代码
  • 应用场景:设计继承体系时,确保子类不改变父类的核心行为;优先使用组合而非继承(如装饰器模式)
接口隔离原则(ISP, Interface Segregation Principle)
  • 定义:客户端不应被迫依赖它不使用的接口

  • 核心思想:将臃肿的接口拆分为更小、更具体的接口,减少不必要的耦合

  • 应用场景

    • 避免“胖接口”(如Java的 java.util.Properties 继承自 Hashtable,但许多方法无用)
    • 使用适配器模式或门面模式隔离接口。
依赖倒置原则(DIP, Dependency Inversion Principle)
  • 定义:高层模块不应依赖低层模块,二者都应依赖抽象;抽象不应依赖细节,细节应依赖抽象
  • 核心思想:通过依赖注入(DI)或工厂模式解耦具体实现
  • 应用场景:需要替换底层实现(如更换数据库、日志框架);使用Spring框架的依赖注入或策略模式实现DIP

第二部分 设计模式详解

创建型模式

单例模式(Singleton)
  • 定义:确保一个类只有一个实例,并提供全局访问点

  • 核心问题:如何避免重复创建对象(如数据库连接池、配置管理器);如何控制全局共享资源的访问

  • 应用场景:全局配置管理类;日志记录器、线程池;缓存、计数器等共享资源

  • 饿汉式:类加载时立即初始化(线程安全,但可能浪费资源)

    public class Singleton {
        private static final Singleton INSTANCE = new Singleton();
        private Singleton() {} // 私有构造
        public static Singleton getInstance() {
            return INSTANCE;
        }
    }
    
  • 懒汉式(双重校验锁) :延迟初始化且线程安全

    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;
        }
    }
    
  • 静态内部类:利用类加载机制保证线程安全

    public class Singleton {
        private Singleton() {}
        private static class Holder {
            static final Singleton INSTANCE = new Singleton();
        }
        public static Singleton getInstance() {
            return Holder.INSTANCE;
        }
    }
    
工厂方法模式(Factory Method)
  • 定义:定义一个创建对象的接口,但让子类决定实例化哪个具体类

  • 核心思想:将对象的创建延迟到子类,实现扩展性;符合开闭原则(新增产品只需新增工厂子类)

  • 结构

    • 抽象工厂接口(定义创建方法)
    • 具体工厂类(实现创建逻辑)
    • 抽象产品接口(定义产品行为)
    • 具体产品类(实现产品功能)
  • 应用场景:跨平台UI组件库(不同操作系统生成不同风格的控件);数据库驱动程序的创建(如MySQL vs PostgreSQL连接器)

  • 代码示例

    // 抽象产品
    interface Button {
        void render();
    }
    // 具体产品:Windows风格按钮
    class WindowsButton implements Button {
        public void render() { System.out.println("Windows按钮渲染"); }
    }
    // 具体产品:Mac风格按钮
    class MacButton implements Button {
        public void render() { System.out.println("Mac按钮渲染"); }
    }
    // 抽象工厂
    interface GUIFactory {
        Button createButton();
    }
    // 具体工厂:Windows工厂
    class WindowsFactory implements GUIFactory {
        public Button createButton() {
            return new WindowsButton();
        }
    }
    // 具体工厂:Mac工厂
    class MacFactory implements GUIFactory {
        public Button createButton() {
            return new MacButton();
        }
    }
    // 客户端代码
    public class Client {
        public static void main(String[] args) {
            GUIFactory factory = new MacFactory(); // 根据配置选择工厂
            Button button = factory.createButton();
            button.render(); // 输出:Mac按钮渲染
        }
    }
    
抽象工厂模式(Abstract Factory)
  • 定义:提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类

  • 工厂方法:针对单一产品等级结构

  • 抽象工厂:针对多个产品等级结构(如UI库中的按钮、文本框、滚动条等)

  • 应用场景:跨平台UI库(保证同一家族的控件风格一致);数据库访问层(统一生成连接、命令、适配器等对象)

  • 代码示例

    // 抽象产品族:按钮、文本框
    interface Button { void render(); }
    interface TextField { void input(); }
    // Mac产品族
    class MacButton implements Button {
        public void render() { System.out.println("Mac按钮"); }
    }
    class MacTextField implements TextField {
        public void input() { System.out.println("Mac文本框输入"); }
    }
    // Windows产品族
    class WindowsButton implements Button { /*...*/ }
    class WindowsTextField implements TextField { /*...*/ }
    // 抽象工厂接口
    interface GUIFactory {
        Button createButton();
        TextField createTextField();
    }
    // 具体工厂:Mac工厂
    class MacFactory implements GUIFactory {
        public Button createButton() { return new MacButton(); }
        public TextField createTextField() { return new MacTextField(); }
    }
    // 客户端代码
    public class Client {
        public static void main(String[] args) {
            GUIFactory factory = new MacFactory();
            Button button = factory.createButton();
            TextField textField = factory.createTextField();
            button.render();       // 输出:Mac按钮
            textField.input();     // 输出:Mac文本框输入
        }
    }
    
建造者模式(Builder)
  • 定义:将复杂对象的构造过程与表示分离,使得同样的构建过程可以创建不同的表示

  • 核心思想:分步骤构造对象(如配置可选参数、处理默认值);避免构造函数参数爆炸(尤其是可选参数多时)

  • 结构

    • Builder接口:定义构建步骤
    • 具体Builder类:实现构建逻辑
    • Director类(可选):指导构建过程(封装构建顺序)
    • Product类:最终构建的复杂对象
  • 应用场景

    • 创建包含多个组件的复杂对象(如XML解析器、SQL查询构造器)
    • 需要生成不同表示的对象(如同一数据导出为PDF、Excel格式)
    • 可选参数较多的对象构造(替代重叠构造器或JavaBean模式)
  • 代码示例

    // 产品:计算机
    class Computer {
        private String cpu;
        private String ram;
        private String storage;
        
        public void setCpu(String cpu) { this.cpu = cpu; }
        public void setRam(String ram) { this.ram = ram; }
        public void setStorage(String storage) { this.storage = storage; }
    }
    // 抽象Builder
    interface ComputerBuilder {
        void buildCpu();
        void buildRam();
        void buildStorage();
        Computer getResult();
    }
    // 具体Builder:游戏电脑
    class GamingComputerBuilder implements ComputerBuilder {
        private Computer computer = new Computer();
        
        public void buildCpu() { computer.setCpu("i9-13900K"); }
        public void buildRam() { computer.setRam("32GB DDR5"); }
        public void buildStorage() { computer.setStorage("2TB NVMe SSD"); }
        public Computer getResult() { return computer; }
    }
    // Director:封装构建流程
    class Director {
        public Computer construct(ComputerBuilder builder) {
            builder.buildCpu();
            builder.buildRam();
            builder.buildStorage();
            return builder.getResult();
        }
    }
    // 客户端代码
    public class Client {
        public static void main(String[] args) {
            Director director = new Director();
            ComputerBuilder builder = new GamingComputerBuilder();
            Computer computer = director.construct(builder);
        }
    }
    
原型模式(Prototype)
  • 定义:通过复制现有对象来创建新对象,而非通过new实例化

  • 核心思想:利用对象克隆避免重复初始化(尤其是构造成本高的对象);支持动态添加或删除原型实例

  • 实现方式

    • 浅拷贝:复制基本类型字段,引用类型字段共享(Java默认clone()方法)
    • 深拷贝:递归复制所有引用对象(需手动实现或序列化)
  • 应用场景:对象创建成本高(如数据库查询结果缓存);需要动态生成对象副本;需要隔离对象与其副本的状态修改

  • 代码示例

    // 原型接口
    interface Prototype extends Cloneable {
        Prototype clone() throws CloneNotSupportedException;
    }
    // 具体原型:简历
    class Resume implements Prototype {
        private String name;
        private String workExperience;
        
        public Resume(String name) { 
            this.name = name; 
            // 模拟耗时初始化(如从数据库加载工作经历)
            this.workExperience = loadWorkExperienceFromDB();
        }
        
        private String loadWorkExperienceFromDB() {
            // 假设此操作耗时较长
            return "工作经验数据...";
        }
        
        @Override
        public Resume clone() throws CloneNotSupportedException {
            return (Resume) super.clone(); // 浅拷贝
        }
    }
    // 客户端代码
    public class Client {
        public static void main(String[] args) throws Exception {
            Resume original = new Resume("张三");
            Resume copy = original.clone(); // 避免重新执行耗时初始化
        }
    }
    
创建型模式对比
模式核心目标典型场景关键区别
单例全局唯一实例配置管理、资源池限制实例数量
工厂方法单个产品的灵活创建跨平台UI控件子类决定实例化类
抽象工厂创建产品家族跨风格UI组件库生产多类相关对象
建造者分步骤构建复杂对象包含多部件的对象构造分离构造过程与表示
原型克隆已有对象避免重复初始化高成本对象的快速复制利用已有对象生成新实例

结构型模式

代理模式
  • 定义:为对象提供一个代理,以控制对其的访问(如权限验证、延迟加载、日志记录等)

  • 核心思想:在不修改原始对象的前提下,增强其功能;代理类与原始类实现同一接口,客户端无感知

  • 结构

    • Subject接口:定义代理和真实对象的共同行为
    • RealSubject:真实业务逻辑的实现
    • Proxy:代理类,持有RealSubject的引用,并在调用前后添加额外逻辑
  • 应用场景:延迟加载(Lazy Initialization):如大型图片加载;访问控制:权限验证、防火墙代理;日志记录或性能监控

  • JDK代理

    // 创建代理对象
    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new LoggingProxy(target)
        );
    }
    // LoggingProxy implements InvocationHandler 重写invoke方法
    
  • CGLIB代理(Code Generation Library)

    // 1. 创建Enhancer实例
    Enhancer enhancer = new Enhancer();
    // 2. 设置父类(目标类)
    enhancer.setSuperclass(UserService.class);
    // 3. 设置回调(方法拦截器)
    enhancer.setCallback(new LogInterceptor());
    // 4. 创建代理对象
    UserService proxy = (UserService) enhancer.create();
    // 5. 通过代理对象调用方法
    proxy.save();
    proxy.finalMethod(); // final方法不会被代理
    // LogInterceptor implements MethodInterceptor 重写intercept方法
    
  • 代码示例:

    // 接口:文件加载器
    interface FileLoader {
        String loadFile(String filename);
    }
    // 真实实现:远程文件加载
    class RemoteFileLoader implements FileLoader {
        public String loadFile(String filename) {
            System.out.println("从远程服务器加载文件:" + filename);
            return "文件内容";
        }
    }
    // 代理:缓存代理
    class CachedFileLoaderProxy implements FileLoader {
        private RemoteFileLoader realLoader;
        private Map<String, String> cache = new HashMap<>();
    ​
        public String loadFile(String filename) {
            if (cache.containsKey(filename)) {
                System.out.println("从缓存加载文件:" + filename);
                return cache.get(filename);
            } else {
                realLoader = new RemoteFileLoader();
                String content = realLoader.loadFile(filename);
                cache.put(filename, content);
                return content;
            }
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            FileLoader loader = new CachedFileLoaderProxy();
            loader.loadFile("data.txt"); // 第一次从远程加载
            loader.loadFile("data.txt"); // 第二次从缓存加载
        }
    }
    
桥接模式
  • 定义:将抽象部分与实现部分分离,使二者可以独立变化

  • 核心思想:通过组合替代继承,避免类爆炸(如多维度变化时的组合问题)

  • 结构

    • Abstraction:抽象类的顶层接口
    • RefinedAbstraction:扩展抽象类
    • Implementor:实现类接口
    • ConcreteImplementor:具体实现
  • 应用场景:UI框架中跨平台渲染(如不同操作系统下的按钮绘制);设备驱动与应用程序的解耦

  • 代码示例

    // 实现接口:绘图引擎
    interface DrawingAPI {
        void drawCircle(double x, double y, double radius);
    }
    // 具体实现:OpenGL绘图
    class OpenGLDrawingAPI implements DrawingAPI {
        public void drawCircle(double x, double y, double radius) {
            System.out.printf("OpenGL画圆:(%f, %f), 半径%f\n", x, y, radius);
        }
    }
    // 抽象类:形状
    abstract class Shape {
        protected DrawingAPI drawingAPI;
        
        protected Shape(DrawingAPI drawingAPI) {
            this.drawingAPI = drawingAPI;
        }
        
        public abstract void draw();
    }
    // 扩展抽象:圆形
    class Circle extends Shape {
        private double x, y, radius;
        
        public Circle(double x, double y, double r, DrawingAPI api) {
            super(api);
            this.x = x;
            this.y = y;
            this.radius = r;
        }
        
        public void draw() {
            drawingAPI.drawCircle(x, y, radius);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            DrawingAPI opengl = new OpenGLDrawingAPI();
            Shape circle = new Circle(10, 20, 5, opengl);
            circle.draw(); // 输出:OpenGL画圆...
        }
    }
    
装饰器模式
  • 定义:动态地为对象添加职责,且比继承更灵活

  • 核心思想:通过组合和委托,实现功能的叠加;装饰器类与被装饰对象实现相同接口

  • 应用场景:动态添加功能(如日志、缓存、压缩);避免子类膨胀(如Java I/O流中的 BufferedInputStream

  • 代码示例

    // 基础接口:数据源
    interface DataSource {
        void writeData(String data);
        String readData();
    }
    // 具体实现:文件数据源
    class FileDataSource implements DataSource {
        public void writeData(String data) { /* 写入文件 */ }
        public String readData() { /* 读取文件 */ return "data"; }
    }
    // 装饰器基类
    abstract class DataSourceDecorator implements DataSource {
        protected DataSource wrappee;
        
        public DataSourceDecorator(DataSource source) {
            this.wrappee = source;
        }
    }
    // 具体装饰器:加密装饰器
    class EncryptionDecorator extends DataSourceDecorator {
        public EncryptionDecorator(DataSource source) {
            super(source);
        }
        
        public void writeData(String data) {
            String encrypted = encrypt(data);
            wrappee.writeData(encrypted);
        }
        
        public String readData() {
            String data = wrappee.readData();
            return decrypt(data);
        }
        
        private String encrypt(String data) { /* 加密逻辑 */ return data; }
        private String decrypt(String data) { /* 解密逻辑 */ return data; }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            DataSource source = new FileDataSource();
            DataSource encryptedSource = new EncryptionDecorator(source);
            encryptedSource.writeData("敏感数据"); // 自动加密后写入
        }
    }
    
适配器模式
  • 定义:将一个接口转换为客户端期望的另一个接口,解决接口不兼容问题

  • 实现方式

    • 类适配器:通过继承实现适配(多语言中可能不支持)
    • 对象适配器:通过组合实现适配(更灵活)
  • 应用场景:整合遗留代码或第三方库;统一多个类的接口(如不同支付网关的适配)

  • 与桥接模式区别:适配器解决已有接口不兼容,桥接模式提前设计抽象与实现分离

  • 代码示例

    // 旧系统:第三方日志接口
    class LegacyLogger {
        void logMessage(String message, int severity) {
            System.out.println("Legacy日志: " + message + ", 级别:" + severity);
        }
    }
    // 新系统要求的日志接口
    interface NewLogger {
        void info(String message);
        void error(String message);
    }
    // 适配器类
    class LoggerAdapter implements NewLogger {
        private LegacyLogger legacyLogger;
        
        public LoggerAdapter(LegacyLogger logger) {
            this.legacyLogger = logger;
        }
        
        public void info(String message) {
            legacyLogger.logMessage(message, 1);
        }
        
        public void error(String message) {
            legacyLogger.logMessage(message, 3);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            NewLogger logger = new LoggerAdapter(new LegacyLogger());
            logger.info("系统启动"); // 转换为旧接口的logMessage调用
        }
    }
    
门面模式
  • 定义:为复杂子系统提供一个统一的高层接口,简化客户端调用

  • 应用场景:简化复杂系统调用流程(如电商下单);为外部系统提供易用的API入口

  • 代码示例

    // 子系统:订单处理
    class InventorySystem {
        boolean checkStock(String productId) { /* 检查库存 */ return true; }
    }
    ​
    class PaymentSystem {
        boolean processPayment(double amount) { /* 处理支付 */ return true; }
    }
    ​
    class ShippingSystem {
        void scheduleDelivery(String address) { /* 安排配送 */ }
    }
    // 门面类
    class OrderFacade {
        private InventorySystem inventory = new InventorySystem();
        private PaymentSystem payment = new PaymentSystem();
        private ShippingSystem shipping = new ShippingSystem();
        
        public boolean placeOrder(String productId, double amount, String address) {
            if (!inventory.checkStock(productId)) return false;
            if (!payment.processPayment(amount)) return false;
            shipping.scheduleDelivery(address);
            return true;
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            OrderFacade facade = new OrderFacade();
            facade.placeOrder("123", 99.9, "北京");
        }
    }
    
组合模式
  • 定义:以树形结构组合对象,使客户端统一处理单个对象和对象组合

  • 结构

    • Component接口:定义叶子和容器的共同行为
    • Leaf:叶子节点(无子节点)
    • Composite:容器节点(可包含子Component)
  • 应用场景:文件系统目录结构;UI组件树(如窗口包含面板、按钮等);组织架构管理(部门与员工)

  • 代码示例

    // Component接口
    interface FileSystemComponent {
        void display();
    }
    // 叶子:文件
    class File implements FileSystemComponent {
        private String name;
        
        public File(String name) { this.name = name; }
        
        public void display() {
            System.out.println("文件:" + name);
        }
    }
    // 容器:文件夹
    class Folder implements FileSystemComponent {
        private String name;
        private List<FileSystemComponent> children = new ArrayList<>();
        
        public Folder(String name) { this.name = name; }
        
        public void add(FileSystemComponent comp) {
            children.add(comp);
        }
        
        public void display() {
            System.out.println("文件夹:" + name);
            for (FileSystemComponent comp : children) {
                comp.display();
            }
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            Folder root = new Folder("根目录");
            root.add(new File("a.txt"));
            
            Folder subDir = new Folder("子文件夹");
            subDir.add(new File("b.doc"));
            root.add(subDir);
            
            root.display(); // 递归显示所有子节点
        }
    }
    
享元模式
  • 定义:通过共享技术高效支持大量细粒度对象

  • 核心思想:分离内部状态(可共享)与外部状态(不可共享);使用工厂缓存共享对象

  • 应用场景:游戏中的大量重复对象(如子弹、树木);文字编辑器中的字符对象;线程池、数据库连接池

  • 代码示例

    // 享元对象:棋子
    class ChessPiece {
        private String color; // 内部状态(可共享)
        
        public ChessPiece(String color) {
            this.color = color;
        }
        
        public void draw(int x, int y) { // 外部状态由客户端传递
            System.out.printf("%s棋子放置在(%d, %d)\n", color, x, y);
        }
    }
    // 享元工厂
    class ChessPieceFactory {
        private static Map<String, ChessPiece> pieces = new HashMap<>();
        
        public static ChessPiece getPiece(String color) {
            if (!pieces.containsKey(color)) {
                pieces.put(color, new ChessPiece(color));
            }
            return pieces.get(color);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            ChessPiece white1 = ChessPieceFactory.getPiece("白");
            ChessPiece white2 = ChessPieceFactory.getPiece("白"); // 复用同一对象
            white1.draw(1, 2);
            white2.draw(3, 4);
        }
    }
    
结构型模式对比
模式核心目标典型场景关键区别
代理控制对象访问权限验证、延迟加载增强访问控制
桥接分离抽象与实现多维度变化的系统避免继承爆炸
装饰器动态添加职责功能叠加(如日志、加密)透明增强功能
适配器接口转换整合遗留系统解决接口不兼容
门面简化复杂子系统调用提供统一API入口封装内部复杂性
组合统一处理树形结构文件系统、UI组件树递归组合对象
享元高效共享细粒度对象大量重复对象的场景分离内部/外部状态

行为型模式

观察者模式
  • 定义:定义对象间的一对多依赖,当一个对象状态改变时,自动通知所有依赖对象

  • 核心思想:解耦发布者(Subject)与订阅者(Observer);支持动态添加或移除观察者

  • 结构

    • Subject接口:管理观察者列表,提供注册/注销方法
    • ConcreteSubject:具体主题,维护状态并触发通知
    • Observer接口:定义更新方法
    • ConcreteObserver:实现更新逻辑
  • 应用场景:事件驱动系统(如GUI按钮点击事件);实时数据推送(股票价格更新、新闻订阅);分布式系统中的服务状态通知

  • 代码示例

    // 主题接口
    interface NewsPublisher {
        void addSubscriber(Subscriber s);
        void removeSubscriber(Subscriber s);
        void notifySubscribers(String news);
    }
    // 具体主题:新闻发布中心
    class NewsCenter implements NewsPublisher {
        private List<Subscriber> subscribers = new ArrayList<>();
        
        public void addSubscriber(Subscriber s) {
            subscribers.add(s);
        }
        
        public void removeSubscriber(Subscriber s) {
            subscribers.remove(s);
        }
        
        public void notifySubscribers(String news) {
            for (Subscriber s : subscribers) {
                s.update(news);
            }
        }
        
        public void publishNews(String news) {
            System.out.println("发布新闻:" + news);
            notifySubscribers(news);
        }
    }
    // 观察者接口
    interface Subscriber {
        void update(String news);
    }
    // 具体观察者:用户
    class User implements Subscriber {
        private String name;
        
        public User(String name) {
            this.name = name;
        }
        
        public void update(String news) {
            System.out.println(name + " 收到新闻:" + news);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            NewsCenter center = new NewsCenter();
            center.addSubscriber(new User("张三"));
            center.addSubscriber(new User("李四"));
            center.publishNews("今日头条:设计模式之美发布!");
        }
    }
    
模板方法模式
  • 定义:在父类中定义算法的骨架,将某些步骤延迟到子类实现

  • 核心思想:通过继承实现代码复用,控制子类扩展点

  • 应用场景:框架中的流程标准化(如Spring的JdbcTemplate);算法步骤固定但部分实现可变(如不同格式的报表生成)

  • 代码示例

    // 抽象类:数据导出模板
    abstract class DataExporter {
        // 模板方法(final防止子类覆盖)
        public final void export() {
            fetchData();
            processData();
            saveToFile();
        }
        
        protected abstract void fetchData();
        protected abstract void processData();
        
        private void saveToFile() {
            System.out.println("保存数据到文件");
        }
    }
    // 具体子类:CSV导出
    class CSVExporter extends DataExporter {
        protected void fetchData() {
            System.out.println("从数据库加载数据");
        }
        
        protected void processData() {
            System.out.println("将数据转换为CSV格式");
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            DataExporter exporter = new CSVExporter();
            exporter.export();
        }
    }
    
策略模式
  • 定义:定义算法族,封装每个算法,使其可互相替换

  • 核心思想:将算法与使用算法的客户端解耦

  • 应用场景:多种算法切换(排序算法、支付方式);需要动态选择行为的系统

  • 代码示例

    // 策略接口:支付方式
    interface PaymentStrategy {
        void pay(double amount);
    }
    // 具体策略:支付宝支付
    class AlipayStrategy implements PaymentStrategy {
        public void pay(double amount) {
            System.out.println("支付宝支付:" + amount + "元");
        }
    }
    // 上下文类:订单
    class Order {
        private PaymentStrategy strategy;
        
        public void setPaymentStrategy(PaymentStrategy strategy) {
            this.strategy = strategy;
        }
        
        public void checkout(double amount) {
            strategy.pay(amount);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            Order order = new Order();
            order.setPaymentStrategy(new AlipayStrategy());
            order.checkout(100.0);
        }
    }
    
责任链模式
  • 定义:将请求的发送者与接收者解耦,使多个对象都有机会处理请求

  • 核心思想:请求沿处理链传递,直到被处理或链结束

  • 应用场景:多级审批流程(如请假审批);过滤器链(如Web请求处理)

  • 代码示例

    // 处理器接口
    interface Handler {
        void handleRequest(Request request);
        void setNext(Handler next);
    }
    // 具体处理器:日志记录
    class LoggerHandler implements Handler {
        private Handler next;
        
        public void setNext(Handler next) {
            this.next = next;
        }
        
        public void handleRequest(Request request) {
            System.out.println("记录请求日志:" + request.getData());
            if (next != null) {
                next.handleRequest(request);
            }
        }
    }
    // 客户端构建责任链
    public class Client {
        public static void main(String[] args) {
            Handler chain = new LoggerHandler();
            chain.setNext(new AuthHandler());
            chain.handleRequest(new Request("敏感数据"));
        }
    }
    
状态模式
  • 定义:允许对象在其内部状态改变时改变行为

  • 应用场景:订单状态流转;游戏角色行为随状态变化

  • 代码示例

    // 状态接口
    interface OrderState {
        void next(Order order);
    }
    // 具体状态:已下单
    class PlacedState implements OrderState {
        public void next(Order order) {
            System.out.println("订单已下单,转为已支付状态");
            order.setState(new PaidState());
        }
    }
    // 上下文类:订单
    class Order {
        private OrderState state;
        
        public Order() {
            state = new PlacedState();
        }
        
        public void nextState() {
            state.next(this);
        }
        
        void setState(OrderState state) {
            this.state = state;
        }
    }
    
迭代器模式
  • 定义:提供一种方法顺序访问聚合对象的元素,而无需暴露其内部表示

  • 应用场景:集合类的遍历;屏蔽不同数据结构(数组、链表)的遍历差异

  • 代码示例

    interface Iterator<T> {
        boolean hasNext();
        T next();
    }
    ​
    class ListIterator<T> implements Iterator<T> {
        private List<T> list;
        private int index = 0;
        
        public ListIterator(List<T> list) {
            this.list = list;
        }
        
        public boolean hasNext() {
            return index < list.size();
        }
        
        public T next() {
            return list.get(index++);
        }
    }
    
访问者模式
  • 定义:将算法与对象结构分离,允许在不修改对象结构的情况下添加新操作。

  • 应用场景:编译器语法树分析;复杂对象结构的统计操作

  • 代码示例

    interface Visitor {
        void visit(ElementA element);
        void visit(ElementB element);
    }
    ​
    class ConcreteVisitor implements Visitor {
        public void visit(ElementA element) {
            System.out.println("处理A元素");
        }
        
        public void visit(ElementB element) {
            System.out.println("处理B元素");
        }
    }
    
备忘录模式
  • 定义:在不破坏封装性的前提下,捕获对象的内部状态,并在需要时恢复该状态

  • 核心思想:分离对象状态的保存与恢复逻辑,支持撤销(Undo)或历史记录功能

  • 结构

    • Originator(原发器) :需要保存状态的对象
    • Memento(备忘录) :存储Originator的内部状态
    • Caretaker(管理者) :负责保存和恢复备忘录
  • 应用场景:文本编辑器的撤销/重做功能;游戏存档与读档;事务回滚机制

  • 代码示例

    // 原发器:文本编辑器
    class TextEditor {
        private String content;
        
        public void write(String text) {
            this.content = text;
        }
        
        public String getContent() {
            return content;
        }
        
        // 创建备忘录
        public TextMemento save() {
            return new TextMemento(content);
        }
        
        // 恢复备忘录
        public void restore(TextMemento memento) {
            this.content = memento.getSavedContent();
        }
    }
    // 备忘录:保存状态
    class TextMemento {
        private final String content;
        
        public TextMemento(String content) {
            this.content = content;
        }
        
        public String getSavedContent() {
            return content;
        }
    }
    // 管理者:管理历史记录
    class History {
        private Stack<TextMemento> stack = new Stack<>();
        
        public void push(TextMemento memento) {
            stack.push(memento);
        }
        
        public TextMemento pop() {
            return stack.pop();
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            TextEditor editor = new TextEditor();
            History history = new History();
            
            editor.write("Hello");
            history.push(editor.save()); // 保存状态
            
            editor.write("Hello World");
            editor.restore(history.pop()); // 撤销到上一状态
            System.out.println(editor.getContent()); // 输出:Hello
        }
    }
    
命令模式
  • 定义:将请求封装为对象,以便参数化客户端请求,支持请求排队、日志记录或撤销操作
  • 核心思想:解耦请求的发送者与接收者,将请求的调用与执行分离
  • 结构

    • Command接口:定义执行方法(如execute())。
    • ConcreteCommand:实现具体命令,绑定接收者与动作。
    • Invoker(调用者) :触发命令执行(如按钮、遥控器)。
    • Receiver(接收者) :实际执行请求的对象。
  • 应用场景:GUI按钮或菜单操作;任务队列、日志记录(支持重做);支持撤销/重做的系统(如绘图软件)

  • 代码示例

    // 接收者:电灯
    class Light {
        public void on() {
            System.out.println("电灯打开");
        }
        public void off() {
            System.out.println("电灯关闭");
        }
    }
    // 命令接口
    interface Command {
        void execute();
    }
    // 具体命令:开灯命令
    class LightOnCommand implements Command {
        private Light light;
        
        public LightOnCommand(Light light) {
            this.light = light;
        }
        
        public void execute() {
            light.on();
        }
    }
    // 调用者:遥控器按钮
    class RemoteControl {
        private Command command;
        
        public void setCommand(Command command) {
            this.command = command;
        }
        
        public void pressButton() {
            command.execute();
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            Light light = new Light();
            Command lightOn = new LightOnCommand(light);
            
            RemoteControl remote = new RemoteControl();
            remote.setCommand(lightOn);
            remote.pressButton(); // 输出:电灯打开
        }
    }
    
解释器模式
  • 定义:定义语言的文法,并提供一个解释器来处理该语言中的句子
  • 核心思想:将特定类型的问题表示为语言规则,通过解释器执行解析
  • 结构

    • 抽象表达式(Expression) :声明解释操作的接口。
    • 终结符表达式(TerminalExpression) :处理语言中的基本元素(如变量、常量)
    • 非终结符表达式(NonterminalExpression) :处理语言中的组合规则(如运算、逻辑判断)
    • 上下文(Context) :包含解释器需要的全局信息
  • 应用场景:SQL、正则表达式解析;数学公式计算器;领域特定语言(DSL)的实现

  • 代码示例

    // 抽象表达式
    interface Expression {
        boolean interpret(Context context);
    }
    // 终结符表达式:变量
    class Variable implements Expression {
        private String name;
        
        public Variable(String name) {
            this.name = name;
        }
        
        public boolean interpret(Context context) {
            return context.get(this.name);
        }
    }
    // 非终结符表达式:逻辑与
    class And implements Expression {
        private Expression left;
        private Expression right;
        
        public And(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
        
        public boolean interpret(Context context) {
            return left.interpret(context) && right.interpret(context);
        }
    }
    // 上下文:存储变量值
    class Context {
        private Map<String, Boolean> variables = new HashMap<>();
        
        public void set(String name, boolean value) {
            variables.put(name, value);
        }
        
        public boolean get(String name) {
            return variables.get(name);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            Context context = new Context();
            context.set("A", true);
            context.set("B", false);
            
            Expression expr = new And(new Variable("A"), new Variable("B"));
            System.out.println(expr.interpret(context)); // 输出:false
        }
    }
    
中介者模式
  • 定义:定义一个中介对象来封装一组对象间的交互,使其耦合度降低,且可以独立改变它们之间的交互

  • 核心思想:将网状的对象交互改为星型结构,中介者作为协调中心

  • 结构

    • Mediator接口:定义同事对象通信的方法
    • ConcreteMediator:协调各同事对象的交互
    • Colleague(同事类) :每个同事类只知道中介者,不直接交互
  • 应用场景:GUI组件间的通信(如对话框中的输入框);多玩家游戏中的角色互动;航班调度系统(协调飞机、跑道、塔台)

  • 代码示例

    // 中介者接口
    interface ChatMediator {
        void sendMessage(String msg, User user);
        void addUser(User user);
    }
    // 具体中介者:聊天室
    class ChatRoom implements ChatMediator {
        private List<User> users = new ArrayList<>();
        
        public void addUser(User user) {
            users.add(user);
        }
        
        public void sendMessage(String msg, User sender) {
            for (User user : users) {
                if (user != sender) { // 不发送给发送者自己
                    user.receive(msg);
                }
            }
        }
    }
    // 同事类:用户
    abstract class User {
        protected ChatMediator mediator;
        protected String name;
        
        public User(ChatMediator mediator, String name) {
            this.mediator = mediator;
            this.name = name;
        }
        
        public abstract void send(String msg);
        public abstract void receive(String msg);
    }
    ​
    class ChatUser extends User {
        public ChatUser(ChatMediator mediator, String name) {
            super(mediator, name);
        }
        
        public void send(String msg) {
            System.out.println(name + " 发送消息:" + msg);
            mediator.sendMessage(msg, this);
        }
        
        public void receive(String msg) {
            System.out.println(name + " 收到消息:" + msg);
        }
    }
    // 客户端
    public class Client {
        public static void main(String[] args) {
            ChatMediator chatRoom = new ChatRoom();
            User alice = new ChatUser(chatRoom, "Alice");
            User bob = new ChatUser(chatRoom, "Bob");
            chatRoom.addUser(alice);
            chatRoom.addUser(bob);
            
            alice.send("你好,Bob!"); 
            // 输出:
            // Alice 发送消息:你好,Bob!
            // Bob 收到消息:你好,Bob!
        }
    }
    
行为型模式对比
模式核心目标典型场景
观察者一对多事件通知实时数据推送、GUI事件
策略算法灵活替换支付方式、排序算法选择
状态行为随状态改变订单状态机、游戏角色行为
责任链请求传递处理链审批流程、过滤器链
访问者分离数据结构与操作语法树分析、报表生成
备忘录保存与恢复对象状态撤销操作、游戏存档
命令封装请求为对象,支持解耦与扩展任务队列、GUI操作管理
解释器解析特定语法规则SQL解析、公式计算
中介者集中管理对象间交互聊天室、复杂UI组件协调