【Java从入门到入土】46设计模式写出优雅代码的套路写代码写到一定阶段你会发现有些问题总是反复出现。比如需要保证一个类只有一个实例、需要根据条件创建不同对象、需要在不修改原有代码的情况下扩展功能……这些问题的解决方案其实就是设计模式。设计模式是前辈们总结出来的“套路”它不是代码模板而是思想。今天我们就来聊聊Java中那些最常用的设计模式看看它们怎么让代码更优雅、更易维护。️ 设计模式三大分类根据目的设计模式分为三类创建型负责对象的创建解耦对象的创建和使用。如单例、工厂、建造者。结构型将类或对象组合成更大的结构。如适配器、装饰器、代理。行为型关注对象之间的交互和职责分配。如策略、观察者、模板方法。我们挑几个最常用的直接上代码。 单例模式Singleton确保一个类只有一个实例并提供一个全局访问点。常见的写法有饿汉式、懒汉式、双重检查锁、静态内部类、枚举。场景配置类、连接池、Spring的Bean默认单例。// 双重检查锁线程安全推荐publicclassSingleton{privatestaticvolatileSingletoninstance;privateSingleton(){}publicstaticSingletongetInstance(){if(instancenull){synchronized(Singleton.class){if(instancenull){instancenewSingleton();}}}returninstance;}}注意volatile防止指令重排序。 工厂模式Factory将对象的创建交给工厂客户端不直接new对象。分为简单工厂、工厂方法、抽象工厂。场景日志记录器、数据库驱动、Spring的BeanFactory。// 简单工厂interfaceProduct{}classProductAimplementsProduct{}classProductBimplementsProduct{}classSimpleFactory{publicstaticProductcreateProduct(Stringtype){if(A.equals(type))returnnewProductA();if(B.equals(type))returnnewProductB();thrownewIllegalArgumentException();}}工厂方法定义一个创建对象的接口让子类决定实例化哪个类。interfaceFactory{Productcreate();}classFactoryAimplementsFactory{publicProductcreate(){returnnewProductA();}} 策略模式Strategy定义一系列算法把它们封装起来并且可以互相替换。策略模式让算法的变化独立于使用算法的客户。场景支付方式选择、促销活动、排序比较器。interfacePaymentStrategy{voidpay(intamount);}classAlipayimplementsPaymentStrategy{publicvoidpay(intamount){System.out.println(使用支付宝支付amount);}}classWechatPayimplementsPaymentStrategy{publicvoidpay(intamount){System.out.println(使用微信支付amount);}}classOrder{privatePaymentStrategystrategy;publicvoidsetStrategy(PaymentStrategystrategy){this.strategystrategy;}publicvoidcheckout(intamount){strategy.pay(amount);}} 观察者模式Observer定义对象之间的一对多依赖当一个对象状态改变时所有依赖者都会收到通知。场景事件监听、消息订阅、Spring的事件机制。importjava.util.ArrayList;importjava.util.List;interfaceObserver{voidupdate(Stringmessage);}classConcreteObserverimplementsObserver{privateStringname;publicConcreteObserver(Stringname){this.namename;}publicvoidupdate(Stringmessage){System.out.println(name 收到消息message);}}classSubject{privateListObserverobserversnewArrayList();publicvoidattach(Observero){observers.add(o);}publicvoidnotifyAllObservers(Stringmessage){for(Observero:observers){o.update(message);}}} 装饰器模式Decorator动态地给对象添加额外的职责比继承更灵活。它通过组合的方式扩展功能。场景Java I/O流BufferedInputStream、给对象增加权限、日志功能。interfaceCoffee{doublecost();Stringdesc();}classSimpleCoffeeimplementsCoffee{publicdoublecost(){return5;}publicStringdesc(){return咖啡;}}// 装饰器基类abstractclassCoffeeDecoratorimplementsCoffee{protectedCoffeecoffee;publicCoffeeDecorator(Coffeecoffee){this.coffeecoffee;}publicdoublecost(){returncoffee.cost();}publicStringdesc(){returncoffee.desc();}}// 加牛奶classMilkDecoratorextendsCoffeeDecorator{publicMilkDecorator(Coffeecoffee){super(coffee);}publicdoublecost(){returnsuper.cost()2;}publicStringdesc(){returnsuper.desc() 牛奶;}}// 使用CoffeecoffeenewMilkDecorator(newSimpleCoffee());System.out.println(coffee.desc() 价格coffee.cost()); 模式对比它们有什么区别工厂 vs 建造者工厂关注创建整体对象建造者关注一步步构建复杂对象如组装电脑。策略 vs 状态策略模式是算法替换状态模式是状态驱动行为状态的切换通常是自动的。装饰器 vs 代理装饰器增强功能代理控制访问。结构上有点像但目的不同。 设计模式在JDK中的应用JDK本身就用满了设计模式看源码时你会发现它们无处不在模式JDK中的应用单例Runtime.getRuntime()、java.lang.System中的SecurityManager工厂Calendar.getInstance()、NumberFormat.getInstance()抽象工厂javax.xml.parsers.DocumentBuilderFactory建造者StringBuilder、StringBuffer适配器java.util.Arrays#asList()、InputStreamReader把字节流转字符流装饰器java.io包里的各种流BufferedInputStream、DataInputStream代理动态代理java.lang.reflect.Proxy迭代器java.util.Iterator、Enumeration观察者java.util.Observer/Observable已过时但思想还在策略java.util.Comparator、ThreadPoolExecutor的拒绝策略模板方法AbstractList、AbstractMap、HttpServlet的service()⚠️ 避免过度设计设计模式是工具不是目的。很多人学完模式就喜欢往代码里套结果本来几行能解决的问题硬是整出好几个接口和类维护起来想骂人。原则简单优于复杂。先让代码跑起来再重构到模式。也就是“你需要在有重构需求的时候才去引入设计模式而不是一开始就预设一堆模式”。比如if-else 能解决就别硬上策略模式简单工厂能搞定就别搞抽象工厂。 总结设计模式是前人踩坑踩出来的经验掌握它们能让你的代码更优雅、更易扩展。但记住单例保证唯一实例。工厂解耦创建和使用。策略让算法自由切换。观察者解耦发布者和订阅者。装饰器动态增强功能。多看JDK源码看看大师们是怎么用模式的。最后送你一句话设计模式不是银弹而是在正确的地方用正确的方法。