前言设计模式是软件开发中经过验证的解决方案它们帮助我们解决常见的软件设计问题。本文将详细介绍三种最常用且重要的设计模式单例模式Singleton Pattern、工厂模式Factory Pattern和代理模式Proxy Pattern。一、单例模式Singleton Pattern1.1 模式概述单例模式是创建型设计模式其核心思想是确保一个类只有一个实例并提供一个全局访问点。这种模式在需要控制资源访问、避免重复创建对象等场景中非常有用。核心特点唯一性一个类只能创建一个实例对象全局访问通过静态方法获取实例整个应用程序共享该实例延迟加载可选在需要时才创建实例节省资源应用场景数据库连接池、日志系统、配置管理器、线程池等。1.2 饿汉式实现public class HungrySingleton { // 类加载时就创建实例线程安全 private static final HungrySingleton instance new HungrySingleton(); // 私有构造函数防止外部实例化 private HungrySingleton() { } // 提供全局访问点 public static HungrySingleton getInstance() { return instance ; } public void showMessage() { System.out.println(Hello from HungrySingleton!); } }代码解释类加载时立即创建instance实例使用final关键字确保引用不可变私有构造函数防止通过new关键字创建实例提供静态方法getInstance获取唯一实例优点实现简单线程安全缺点类加载时就创建实例即使不使用也会占用资源可能造成资源浪费1.3 懒汉式实现public class LazySingleton { private static LazySingleton instance; private LazySingleton() { } // 同步方法获取实例保证线程安全 public static synchronized LazySingleton getInstance() { if (instance null) { instance new LazySingleton(); } return instance; } }代码解释synchronized关键字修饰后保证在多线程环境下只创建一个实例加锁和if判断双重检查只有实例为空时才创建实现了延迟加载节省资源缺点每次调用getInstance都需要加锁性能开销较大1.4 双重检查锁定实现public class DoubleCheckedSingleton { // volatile确保可见性和禁止指令重排序 private static volatile DoubleCheckedSingleton instance; private DoubleCheckedSingleton() { } public static DoubleCheckedSingleton getInstance() { // 第一次检查避免不必要的同步 if (instance null) { synchronized (DoubleCheckedSingleton.class) { // 第二次检查确保在多线程环境下只创建一个实例 if (instance null) { instance new DoubleCheckedSingleton(); } } } return instance; } }代码解释:用volatile修饰,确保多线程环境下instance变量的可见性防止指令重排序第一次进行if判断是为了减少不必要的加锁提升性能同步代码块内的第二次检查, 确保在多线程环境下只创建一个实例优点延迟加载、线程安全、性能优秀是推荐的实现方式1.5 静态内部类实现public class StaticInnerClassSingleton { private StaticInnerClassSingleton() { } // 静态内部类只有在调用getInstance()时才会被加载 private static class SingletonHolder { private static final StaticInnerClassSingleton instance new StaticInnerClassSingleton(); } public static StaticInnerClassSingleton getInstance() { return SingletonHolder.instance ; } }代码解释创建一个静态内部类只有在调用getInstance()时才会被加载静态内部类的实例创建发生在被加载时且由JVM保证线程安全这种方式既实现了延迟加载又保证了线程安全是最佳实现方式优点延迟加载、线程安全、性能优秀是推荐的实现方式1.6 单例模式总结实现方式延迟加载线程安全性能推荐程度饿汉式否是优一般懒汉式是是差不推荐双重检查锁定是是优推荐静态内部类是是优推荐二、工厂模式Factory Pattern2.1 模式概述工厂模式是创建型设计模式其核心思想是将对象的创建与使用分离通过工厂类来创建对象。这种模式降低了客户端代码与具体产品类之间的耦合度提高了系统的可维护性和可扩展性。模式分类简单工厂Simple Factory一个工厂类根据参数创建不同的产品工厂方法Factory Method定义一个创建对象的接口由子类决定实例化哪个类抽象工厂Abstract Factory提供一个创建一系列相关对象的接口2.2 简单工厂模式// 产品接口 public interface Product { void operation(); } // 具体产品A public class ConcreteProductA implements Product { Override public void operation() { System.out.println(ConcreteProductA operation); } } // 具体产品B public class ConcreteProductB implements Product { Override public void operation() { System.out.println(ConcreteProductB operation); } } // 简单工厂 public class SimpleFactory { public Product createProduct(String type) { if (A.equals(type)) { return new ConcreteProductA(); } else if (B.equals(type)) { return new ConcreteProductB(); } else { throw new IllegalArgumentException(Unknown product type: type); } } } // 客户端使用 public class SimpleFactoryClient { public static void main(String[] args) { SimpleFactory factory new SimpleFactory(); Product productA factory.createProduct(A); productA.operation(); } }代码解释product接口定义产品的通用行为所有产品都实现这个接口simpleFactory是一个简单工厂类根据参数创建相应的产品对象客户端代码通过工厂类获取产品无需知道具体的产品类名优点封装了对象创建过程客户端代码与具体产品类解耦缺点违反开闭原则增加新产品需要修改工厂类的d2.3 工厂方法模式// 产品接口 public interface Product { void operation(); } // 具体产品 public class ConcreteProductA implements Product { Override public void operation() { System.out.println(ConcreteProductA operation); } } public class ConcreteProductB implements Product { Override public void operation() { System.out.println(ConcreteProductB operation); } } // 抽象工厂接口 public interface Factory { Product createProduct(); } // 具体工厂A - 创建产品A public class ConcreteFactoryA implements Factory { Override public Product createProduct() { return new ConcreteProductA(); } } // 具体工厂B - 创建产品B public class ConcreteFactoryB implements Factory { Override public Product createProduct() { return new ConcreteProductB(); } } // 客户端使用 public class FactoryMethodClient { public static void main(String[] args) { Factory factoryA new ConcreteFactoryA(); Product productA factoryA.createProduct(); productA.operation(); } }代码解释Factory接口用来定义创建产品的抽象方法ConcreteProductA和 ConcreteProductB都是具体工厂类负责创建具体产品每个工厂只负责创建一种产品符合单一职责原则客户端依赖抽象工厂接口和抽象产品接口添加的新产品类只需要实现Factory接口即可优点符合开闭原则新增产品只需添加新的工厂类2.4 抽象工厂模式// 产品族接口A public interface ProductA { void operationA(); } // 产品族接口B public interface ProductB { void operationB(); } // 产品实现 public class ProductA1 implements ProductA { Override public void operationA() { System.out.println(ProductA1 operationA); } } public class ProductB1 implements ProductB { Override public void operationB() { System.out.println(ProductB1 operationB); } } // 抽象工厂接口 - 可创建多个产品族 public interface AbstractFactory { ProductA createProductA(); ProductB createProductB(); } // 具体工厂1 - 创建产品族1 public class ConcreteFactory1 implements AbstractFactory { Override public ProductA createProductA() { return new ProductA1(); } Override public ProductB createProductB() { return new ProductB1(); } } // 客户端使用 public class AbstractFactoryClient { public static void main(String[] args) { AbstractFactory factory1 new ConcreteFactory1(); ProductA productA1 factory1.createProductA(); ProductB productB1 factory1.createProductB(); productA1.operationA(); productB1.operationB(); } }代码解释抽象工厂模式用于创建产品族一系列相关的产品AbstractFactory接口定义创建多个产品的方法客户端代码可以切换整个产品族而不需要修改其他代码优点可以创建一系列相关的产品对象符合开闭原则2.5 工厂模式对比特性简单工厂工厂方法抽象工厂产品复杂度单一产品单一产品族多产品族开闭原则违反符合部分符合代码复杂度低中高适用场景产品类型少产品种类多产品族多三、代理模式Proxy Pattern3.1 模式概述代理模式是结构型设计模式其核心思想是为另一个对象提供一个替身或占位符以控制对这个对象的访问。代理对象可以在不改变目标对象的情况下增加额外的功能操作。模式角色Subject真实对象的抽象定义目标对象和代理对象的公共接口RealSubject真实对象定义代理对象所代表的真实实体Proxy代理保存一个引用使得代理可以访问实体并提供与主题相同的接口应用场景远程代理、虚拟代理、安全代理、智能引用等。3.2 静态代理// 真实对象的抽象接口 public interface Subject { void request(); } // 真实对象 - 实现实际的业务逻辑 public class RealSubject implements Subject { Override public void request() { System.out.println(RealSubject: 处理实际请求); } } // 代理类 - 在调用真实对象前后进行增强 public class ProxySubject implements Subject { private RealSubject realSubject; public ProxySubject() { this.realSubject new RealSubject(); } Override public void request() { // 调用真实对象之前的操作 System.out.println(ProxySubject: 调用前的准备工作); // 调用真实对象的方法 realSubject.request(); // 调用真实对象之后的操作 System.out.println(ProxySubject: 调用后的清理工作); } } // 客户端使用 public class StaticProxyClient { public static void main(String[] args) { Subject subject new ProxySubject(); subject.request(); } }代码解释Subject接口定义代理和真实对象的公共接口RealSubject实现实际业务逻辑的真实主题ProxySubject代理类在调用真实主题方法前后添加额外操作优点可以在不修改真实主题的情况下增加功能缺点需要为每个真实主题创建代理类代码量大时难以维护3.3 JDK动态代理import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 真实对象的抽象接口 public interface Subject { void request(); String getData(); } // 真实对象 public class RealSubject implements Subject { Override public void request() { System.out.println(RealSubject: 处理实际请求); } Override public String getData() { return RealSubject: 数据; } } // InvocationHandler实现类 - 包含增强逻辑 public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target target; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 调用前的增强逻辑 System.out.println(方法 method.getName() 调用前); // 调用目标对象的方法 Object result method.invoke(target, args); // 调用后的增强逻辑 System.out.println(方法 method.getName() 调用后); return result; } } // JDK动态代理客户端 public class DynamicProxyClient { public static void main(String[] args) { RealSubject realSubject new RealSubject(); MyInvocationHandler handler new MyInvocationHandler(realSubject); // 创建代理对象 Subject proxySubject (Subject) Proxy.newProxyInstance( RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), handler ); proxySubject.request(); System.out.println(获取到的数据: proxySubject.getData()); } }代码解释InvocationHandler接口动态代理的核心包含了增强逻辑invoke方法当调用代理对象的方法时会自动调用这个方法Proxy.newProxyInstance在运行时动态创建代理对象代理对象实现了目标对象的所有接口优点可以在运行时动态创建代理无需为每个类编写代理类缺点只能代理接口不能代理具体类3.4 代理模式应用实例import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; // 计算接口 interface Calculator { int add(int a, int b); int subtract(int a, int b); } // 计算器实现 class CalculatorImpl implements Calculator { Override public int add(int a, int b) { return a b; } Override public int subtract(int a, int b) { return a - b; } } // 计算器代理带日志和性能监控 class CalculatorProxy implements InvocationHandler { private Calculator target; public CalculatorProxy(Calculator target) { this.target target; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime System.currentTimeMillis(); // 日志 System.out.println(方法 method.getName() 开始执行参数: Arrays.toString(args)); // 调用实际方法 Object result method.invoke(target, args); long endTime System.currentTimeMillis(); System.out.println(方法 method.getName() 执行完成结果: result); System.out.println(执行耗时: (endTime - startTime) ms); return result; } } // 代理模式应用测试 public class ProxyPatternDemo { public static void main(String[] args) { CalculatorImpl calculator new CalculatorImpl(); InvocationHandler handler new CalculatorProxy(calculator); Calculator proxyCalculator (Calculator) Proxy.newProxyInstance( CalculatorImpl.class.getClassLoader(), CalculatorImpl.class.getInterfaces(), handler ); // 使用代理计算器 int result1 proxyCalculator.add(10, 5); System.out.println(10 5 result1); int result2 proxyCalculator.subtract(10, 5); System.out.println(10 - 5 result2); } }运行结果方法 add 开始执行参数: [10, 5] 方法 add 执行完成结果: 15 执行耗时: 0ms 10 5 15 方法 subtract 开始执行参数: [10, 5] 方法 subtract 执行完成结果: 5 执行耗时: 0ms 10 - 5 5代码解释CalculatorProxy为Calculator添加了日志和性能监控功能客户端使用代理对象调用方法无需修改原有代码代理模式实现了业务逻辑和增强逻辑的分离四、模式对比与总结4.1 三种模式对比模式类型核心作用优点缺点单例模式创建型确保唯一实例控制资源、全局访问可能过度使用工厂模式创建型封装对象创建解耦、符合开闭原则增加类数量代理模式结构型控制对象访问增强功能、安全控制增加调用复杂度4.2 使用建议单例模式用于确实只需要一个实例的场景推荐使用双重检查锁定或静态内部类实现。工厂模式当对象创建逻辑复杂时使用根据复杂度选择简单工厂、工厂方法或抽象工厂优先考虑工厂方法模式。代理模式需要在访问对象时添加额外功能时使用优先使用JDK动态代理无法代理类时使用CGLIB。4.3 模式组合使用在实际开发中这三种模式经常组合使用import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; // 代理工厂单例 工厂 代理 public class ProxyFactory { // 单例 private static ProxyFactory instance; private ProxyFactory() { } public static ProxyFactory getInstance() { if (instance null) { synchronized (ProxyFactory.class) { if (instance null) { instance new ProxyFactory(); } } } return instance; } // 工厂方法创建代理 public T T createProxy(T target, InvocationHandler handler) { return (T) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler ); } }结语设计模式是软件开发中的重要工具合理使用可以提高代码的可维护性、可扩展性和可读性。本文详细介绍了单例模式、工厂模式和代理模式的核心概念、实现方式和应用场景。通过大量的代码示例和详细解释相信您已经对这三个模式有了深入的理解。在实际开发中应该根据具体场景选择合适的模式并注意模式组合使用时的权衡和取舍