目录

一、单例模式(Singleton Pattern)

【1】核心思想

【2】适用场景

【3】实现方式:双重检查锁(线程安全)

【4】优点

二、工厂模式(Factory Pattern)

【1】核心思想

【2】适用场景

【3】实现方式:简单工厂模式

【4】优点

三、观察者模式(Observer Pattern)

【1】核心思想

【2】适用场景

【3】实现方式

【4】优点

四、装饰器模式(Decorator Pattern)

【1】核心思想

【2】适用场景

【3】实现方式

【4】优点

五、策略模式(Strategy Pattern)

【1】核心思想

【2】适用场景

【3】实现方式

【4】优点

六、适配器模式(Adapter Pattern)

【1】核心思想

【2】适用场景

【3】实现方式:对象适配器

【4】优点

七、代理模式(Proxy Pattern)

【1】核心思想

【2】适用场景

【3】实现方式:静态代理

【4】优点

八、总结


一、单例模式(Singleton Pattern)

【1】核心思想

保证一个类仅有一个实例,并提供一个全局访问点。

【2】适用场景

  • 配置文件管理器
  • 日志工具类
  • 线程池、连接池等资源管理器

【3】实现方式:双重检查锁(线程安全)

public class Singleton {
    //  volatile 防止指令重排序
    private static volatile volatile Singleton instance;
    
    // 私有构造方法,防止外部实例化
    private Singleton() {}
    
    // 双重检查锁实现
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

【4】优点

  • 节省系统资源,避免频繁创建销毁对象
  • 全局唯一实例,便于协调系统行为

二、工厂模式(Factory Pattern)

【1】核心思想

定义一个创建对象的接口,让子类的子类决定实例化哪个类,使实例化延迟到子类。

【2】适用场景

  • 对象创建逻辑复杂,需要集中管理
  • 需要根据不同条件创建不同类型的对象
  • 解耦对象的创建和使用

【3】实现方式:简单工厂模式

// 产品接口
public interface Shape {
    void draw();
}

// 具体产品
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画圆形");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("画矩形");
    }
}

// 工厂类
public class ShapeFactory {
    // 根据类型创建对应对象
    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        }
        return null;
    }
}

// 使用示例
public class FactoryPatternDemo {
    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();
        
        Shape shape1 = shapeFactory.getShape("CIRCLE");
        shape1.draw(); // 输出:画圆形
        
        Shape shape2 = shapeFactory.getShape("RECTANGLE");
        shape2.draw(); // 输出:画矩形
    }
}

【4】优点

  • 降低代码耦合度,符合开闭原则
  • 便于扩展,新增产品只需添加新的实现类和工厂逻辑

三、观察者模式(Observer Pattern)

【1】核心思想

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

【2】适用场景

  • 事件监听机制
  • 消息通知系统
  • 实时数据展示(如股票行情)

【3】实现方式

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

// 主题接口
public interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

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

// 具体主题
public class NewsSubject implements Subject {
    private List<Observer> observers;
    private String message;
    
    public NewsSubject() {
        observers = new ArrayList<>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }
    
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
    
    // 发布新闻
    public void setNews(String news) {
        this.message = news;
        notifyObservers(); // 通知所有观察者
    }
}

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

// 使用示例
public class ObserverPatternDemo {
    public static void main(String[] args) {
        NewsSubject newsSubject = new NewsSubject();
        
        Observer user1 = new UserObserver("张三");
        Observer user2 = new UserObserver("李四");
        
        newsSubject.registerObserver(user1);
        newsSubject.registerObserver(user2);
        
        newsSubject.setNews("Java 设计模式详解发布啦!");
        // 输出:
        // 张三 收到新闻:Java 设计模式详解发布啦!
        // 李四 收到新闻:Java 设计模式详解发布啦!
    }
}

【4】优点

  • 实现观察者与被观察者解耦
  • 支持动态添加和移除观察者

四、装饰器模式(Decorator Pattern)

【1】核心思想

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

【2】适用场景

  • 需要动态扩展类的功能,且不影响其他对象
  • 不适合通过继承实现的场景(如继承层次过深)

【3】实现方式

// 抽象组件
public interface Beverage {
    String getDescription();
    double cost();
}

// 具体组件
public class Coffee implements Beverage {
    @Override
    public String getDescription() {
        return "黑咖啡";
    }
    
    @Override
    public double cost() {
        return 20.0;
    }
}

// 装饰器抽象类
public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;
    
    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription();
    }
}

// 具体装饰器
public class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + ",加牛奶";
    }
    
    @Override
    public double cost() {
        return beverage.cost() + 5.0;
    }
}

public class Sugar extends CondimentDecorator {
    public Sugar(Beverage beverage) {
        super(beverage);
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + ",加糖";
    }
    
    @Override
    public double cost() {
        return beverage.cost() + 2.0;
    }
}

// 使用示例
public class DecoratorPatternDemo {
    public static void main(String[] args) {
        // 基础咖啡
        Beverage beverage = new Coffee();
        System.out.println(beverage.getDescription() + " 价格:" + beverage.cost());
        
        // 加牛奶的咖啡
        Beverage milkCoffee = new Milk(new Coffee());
        System.out.println(milkCoffee.getDescription() + " 价格:" + milkCoffee.cost());
        
        // 加牛奶和糖的咖啡
        Beverage milkSugarCoffee = new Sugar(new Milk(new Coffee()));
        System.out.println(milkSugarCoffee.getDescription() + " 价格:" + milkSugarCoffee.cost());
    }
}

【4】优点

  • 可以灵活组合功能,避免类爆炸
  • 符合开闭原则,扩展方便

五、策略模式(Strategy Pattern)

【1】核心思想

定义一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而变化。

【2】适用场景

  • 多个类只有算法或行为不同的场景
  • 需要动态切换算法的场景
  • 避免使用多重条件判断(if-else/switch)

【3】实现方式

// 策略接口
public interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略
public class AliPayStrategy implements PaymentStrategy {
    private String username;
    
    public AliPayStrategy(String username) {
        this.username = username;
    }
    
    @Override
    public void pay(double amount) {
        System.out.println(username + " 使用支付宝支付了 " + amount + " 元");
    }
}

public class WechatPayStrategy implements PaymentStrategy {
    private String phoneNumber;
    
    public WechatPayStrategy(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
    
    @Override
    public void pay(double amount) {
        System.out.println(phoneNumber + " 使用微信支付了 " + amount + " 元");
    }
}

// 上下文类
public class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
    
    public void checkout(double amount) {
        paymentStrategy.pay(amount);
    }
}

// 使用示例
public class StrategyPatternDemo {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        
        // 选择支付宝支付
        cart.setPaymentStrategy(new AliPayStrategy("zhangsan@example.com"));
        cart.checkout(199.9);
        
        // 切换为微信支付
        cart.setPaymentStrategy(new WechatPayStrategy("13800138000"));
        cart.checkout(299.5);
    }
}

【4】优点

  • 算法可以自由切换
  • 避免使用多重条件判断
  • 扩展性良好,新增算法只需实现接口

六、适配器模式(Adapter Pattern)

【1】核心思想

将一个类的接口转换成客户端希望的另一个接口,使原本因接口不兼容而无法一起工作的类可以协同工作。

【2】适用场景

  • 集成第三方组件,但其接口与现有系统不匹配
  • 重构旧系统时,需要兼容新的接口规范
  • 统一多个类的接口,便于客户端调用

【3】实现方式:对象适配器

// 目标接口(客户端期望的接口)
public interface Target {
    void request();
}

// 适配者(需要被适配的类)
public class Adaptee {
    // 适配者的特定方法
    public void specificRequest() {
        System.out.println("执行适配者的业务逻辑");
    }
}

// 适配器类
public class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        // 适配过程:将目标接口的方法转换为适配者的方法
        adaptee.specificRequest();
    }
}

// 使用示例
public class AdapterPatternDemo {
    public static void main(String[] args) {
        // 创建适配者对象
        Adaptee adaptee = new Adaptee();
        // 创建适配器,包装适配者
        Target target = new Adapter(adaptee);
        // 客户端通过目标接口调用,实际执行的是适配者的逻辑
        target.request();
    }
}

【4】优点

  • 解决接口不兼容问题,提高代码复用性
  • 无需修改原有代码,符合开闭原则
  • 灵活性高,可动态切换不同的适配者

七、代理模式(Proxy Pattern)

【1】核心思想

为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用。

【2】适用场景

  • 远程代理:如 RPC 框架中代理远程服务
  • 安全代理:控制对敏感对象的访问权限
  • 延迟加载:在需要时才初始化目标对象(如 Hibernate 的懒加载)
  • 日志记录:在方法调用前后记录日志

【3】实现方式:静态代理

// 主题接口
public interface Image {
    void display();
}

// 真实主题(被代理对象)
public class RealImage implements Image {
    private String fileName;
    
    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(); // 模拟从磁盘加载图片(耗时操作)
    }
    
    private void loadFromDisk() {
        System.out.println("加载图片: " + fileName);
    }
    
    @Override
    public void display() {
        System.out.println("显示图片: " + fileName);
    }
}

// 代理类
public class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;
    
    public ProxyImage(String fileName) {
        this.fileName = fileName;
    }
    
    @Override
    public void display() {
        // 延迟初始化:只有当真正需要显示时才创建真实对象
        if (realImage == null) {
            realImage = new RealImage(fileName);
        }
        // 可以在这里添加额外逻辑,如日志记录、权限检查等
        System.out.println("Proxy: 准备显示图片");
        realImage.display();
        System.out.println("Proxy: 显示完成");
    }
}

// 使用示例
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 创建代理对象(此时并未加载图片)
        Image image = new ProxyImage("test.jpg");
        
        // 第一次调用display(),才会真正加载并显示图片
        image.display();
        System.out.println("---");
        // 第二次调用,直接使用已创建的真实对象
        image.display();
    }
}

【4】优点

  • 保护目标对象,控制访问权限
  • 实现延迟加载,提高系统性能
  • 便于在不修改目标对象的前提下添加额外功能(如日志、事务)

八、总结

设计模式是解决特定问题的最佳实践,掌握这些模式能帮助我们写出更优雅、可维护的代码。以上 7 种设计模式是 Java 开发中最常用的,总结如下:

  1. 单例模式:控制对象创建,适合全局资源管理

  2. 工厂模式:封装对象创建逻辑,解耦创建与使用

  3. 观察者模式:实现对象间的联动通信,适合事件驱动场景

  4. 装饰器模式:动态扩展功能,避免继承层次过深

  5. 策略模式:封装不同算法,实现灵活切换

  6. 适配器模式:解决接口不兼容问题,便于集成第三方组件

  7. 代理模式:控制对象访问,实现延迟加载和功能增强


        感谢你花时间读到这里~ 如果你觉得这篇内容对你有帮助,不妨点个赞让更多人看到;如果有任何想法、疑问,或者想分享你的相关经历,欢迎在评论区留言交流,你的每一条互动对我来说都很珍贵~ 我们下次再见啦!😊😊

更多推荐