写在前面刚学Java的时候我被“设计模式”这个词吓住了——单例、工厂、策略、代理……感觉是高手才需要掌握的“秘籍”。面试前拼命背六大原则23种模式每个模式的UML图……可实际写项目时我却很少主动使用它们。不是不会写而是觉得“没必要”——一个简单的功能写个if-else就完了何必套一层工厂一个类能搞定的事为什么要拆出接口直到某天接手老项目看到一个上千行的类里面密密麻麻全是if (type 1) ... else if (type 2) ...改一个bug要翻半天加一个新类型要改好几个地方——这才明白设计模式不是炫技而是让代码更容易扩展、维护、被他人理解。其实很多模式我们每天都在用Spring的Autowired就是依赖倒置java.util.Collections.singletonList()就是工厂方法ThreadLocal用到了单例思想……只是我们没意识到而已。这篇笔记我决定抛开枯燥的UML图从“为什么要这样写”出发结合真实代码场景讲清楚六大原则的核心理念以及最常用的五种设计模式单例、工厂、策略、模板方法、适配器。看完你会发现设计模式没那么玄乎它只是前人总结的“最佳实践”而已。1️⃣ 为什么需要设计模式先看一段“反模式”代码public class OrderService { public void process(String type) { if (normal.equals(type)) { // 普通订单处理逻辑50行 } else if (vip.equals(type)) { // VIP订单处理逻辑60行 } else if (group.equals(type)) { // 团购订单处理逻辑70行 } // 后面还要加新类型再写一个else if... } }这段代码有什么问题难以扩展加一个新类型必须修改这个类违反开闭原则。难以测试想单独测试VIP逻辑必须构造整个OrderService对象。重复代码不同分支可能有共同的预处理逻辑却没有复用。用策略模式改造后public interface OrderStrategy { void process(); } Component public class NormalOrderStrategy implements OrderStrategy { ... } Component public class VipOrderStrategy implements OrderStrategy { ... } Service public class OrderService { Autowired private MapString, OrderStrategy strategies; // key bean名称 public void process(String type) { strategies.get(type OrderStrategy).process(); } }加新类型新增一个类即可不用改OrderService——这就是设计模式的力量。2️⃣ 六大原则代码设计的“交通规则”设计模式是招式六大原则是内功。理解原则才能真正灵活运用模式。S – 单一职责原则 (Single Responsibility Principle)一个类只做一件事只有一个被修改的理由。反例一个User类既有用户属性又有数据校验逻辑还要管数据库操作。正确拆分User实体、UserValidator校验、UserRepository持久化。O – 开闭原则 (Open-Closed Principle)对扩展开放对修改关闭。核心新增功能时尽量不修改现有代码而是通过新增类/方法实现。实例上面策略模式的例子——加新策略只加类不改OrderService。L – 里氏替换原则 (Liskov Substitution Principle)子类必须能替换父类且程序行为不变。反例正方形继承矩形但设置宽高行为不一致导致替换后逻辑出错。正确不为了代码复用强行继承优先使用组合。I – 接口隔离原则 (Interface Segregation Principle)接口应该小而专一不要设计“胖接口”。反例一个Worker接口有work()、eat()、sleep()但机器人实现它时必须空实现eat()。正确拆分成Workable、Eatable机器人只实现Workable。D – 依赖倒置原则 (Dependency Inversion Principle)依赖抽象而不是具体实现。实例Spring的Autowired注入接口而不是实现类。这样切换实现时调用方无需修改。好处解耦方便单元测试可以Mock接口。迪米特法则 (Law of Demeter) / 最少知识原则一个对象应该与其他对象保持最少的了解。通俗不要和陌生人说话。只与直接的朋友通信。反例order.getUser().getAddress().getCity()这种链式调用过度暴露内部结构。改进order.getUserCity()封装获取逻辑。六大原则关系图3️⃣ 创建型模式单例模式保证一个类只有一个实例并提供全局访问点。使用场景配置文件管理、日志记录器、数据库连接池、Spring中的Bean默认单例。几种写法对比推荐实现静态内部类public class Singleton { private Singleton() {} // 私有构造器 private static class SingletonHolder { private static final Singleton INSTANCE new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }推荐实现枚举最安全javapublic enum Singleton { INSTANCE; public void doSomething() { ... } }4️⃣ 创建型模式工厂模式将对象的创建和使用分离调用方不需要知道具体构造细节。简单工厂不属于23种模式一个工厂类根据参数返回不同产品。缺点增加新产品要改工厂类违反开闭原则。public class SimpleFactory { public static Product create(String type) { if (A.equals(type)) return new ProductA(); else if (B.equals(type)) return new ProductB(); else throw new IllegalArgumentException(); } }工厂方法模式定义创建对象的接口由子类决定实例化哪个类。符合开闭原则。public interface Factory { Product create(); } public class ProductAFactory implements Factory { public Product create() { return new ProductA(); } } public class ProductBFactory implements Factory { public Product create() { return new ProductB(); } }Spring中的应用FactoryBean接口用于创建复杂Bean。抽象工厂模式创建一系列相关或相互依赖的产品族。实例不同的数据库MySQL、Oracle需要各自生成Connection、Statement、ResultSet。抽象工厂定义创建这些对象的接口具体工厂实现各数据库的创建逻辑。5️⃣ 行为型模式策略模式定义一系列算法将每个算法封装起来使它们可以互相替换。结构上下文Context持有策略接口的引用。策略接口Strategy定义算法通用方法。具体策略Concrete Strategy实现算法。实战支付方式选择// 策略接口 public interface PaymentStrategy { void pay(double amount); } // 具体策略 public class AlipayStrategy implements PaymentStrategy { public void pay(double amount) { System.out.println(使用支付宝支付 amount); } } public class WechatPayStrategy implements PaymentStrategy { public void pay(double amount) { System.out.println(使用微信支付 amount); } } // 上下文 public class PaymentContext { private PaymentStrategy strategy; public void setStrategy(PaymentStrategy strategy) { this.strategy strategy; } public void executePay(double amount) { strategy.pay(amount); } } // 使用 PaymentContext ctx new PaymentContext(); ctx.setStrategy(new AlipayStrategy()); ctx.executePay(100);与工厂模式结合工厂模式负责创建策略对象策略模式负责执行算法。Spring中可以通过MapString, Strategy自动注入所有策略Bean实现动态选择。6️⃣ 行为型模式模板方法模式定义一个操作中的算法骨架将某些步骤延迟到子类中实现。结构抽象模板定义骨架方法final以及基本步骤方法抽象或钩子。具体子类实现抽象方法。实例饮料制作public abstract class BeverageMaker { // 模板方法声明为final防止子类修改顺序 public final void make() { boilWater(); brew(); pourInCup(); addCondiments(); } private void boilWater() { System.out.println(煮沸水); } private void pourInCup() { System.out.println(倒入杯子); } protected abstract void brew(); // 冲泡茶/咖啡不同 protected abstract void addCondiments(); // 加调料 } public class TeaMaker extends BeverageMaker { protected void brew() { System.out.println(浸泡茶叶); } protected void addCondiments() { System.out.println(加柠檬); } }Spring中的应用JdbcTemplate执行查询的流程固定但结果映射由子类实现。AbstractController、AbstractHandlerMapping等。7️⃣ 结构型模式适配器模式将一个类的接口转换成客户端期望的另一个接口使不兼容的类可以一起工作。场景老系统的接口与新系统不匹配。第三方库的接口与你需要的不同。实现方式// 目标接口 public interface Target { void request(); } // 需要适配的类Adaptee public class Adaptee { public void specificRequest() { System.out.println(特殊请求); } } // 类适配器继承 public class ClassAdapter extends Adaptee implements Target { public void request() { specificRequest(); } } // 对象适配器组合 public class ObjectAdapter implements Target { private Adaptee adaptee; public ObjectAdapter(Adaptee adaptee) { this.adaptee adaptee; } public void request() { adaptee.specificRequest(); } }Spring中的应用HandlerAdapter将不同类型的Controller注解、Servlet、Function适配成统一的执行接口。日志框架SLF4J适配不同日志实现。8️⃣ 总结与选型建议原则 vs 模式先遵循六大原则尤其是开闭和依赖倒置自然就会用上某些模式。不要为了用模式而用模式简单if-else能搞定且不会频繁变化就别硬套。个人建议从单例和工厂开始因为Spring每天都在用。遇到多种算法分支时立刻想到策略模式。写公共库时用模板方法留出扩展点。代码评审时用六大原则评判现有设计。你平时在项目中最常用到哪种设计模式有没有因为“过度设计”而把简单问题复杂化的经历比如强行套用策略模式结果只有两种算法而且几乎不会扩展。或者有没有因为“违背原则”而导致后期维护困难的惨痛教训欢迎在评论区分享你的案例。