Spring Boot 经典九设计模式全览

在Spring Boot中,设计模式的应用广泛且重要,它们有助于提高代码的可维护性、可扩展性和复用性。以下是Spring Boot中经典的9种设计模式及其代码案例:

1. 单例模式(Singleton Pattern)

在Spring中,bean默认就是单例模式。Spring通过单例注册表的方式来实现单例,即维护一个Map来存储单例类的实例。

复制代码
   // 单例模式示例
   public class SingletonService {
       private static SingletonService instance;
       private SingletonService() {}
       public static SingletonService getInstance() {
           if (instance == null) {
               instance = new SingletonService();
           }
           return instance;
       }
   }
2. 工厂模式(Factory Pattern)

工厂模式用于创建对象,而无需指定创建对象的具体类。Spring Boot中可以通过@Bean注解在配置类中实现工厂方法。

1. 定义接口或抽象类
复制代码
// 用户接口  
public interface ReturnUser {  
    List<String> getUserByType();  
} 
2. 实现接口或继承抽象类

然后,创建实现该接口或继承该抽象类的具体类。

复制代码
// 机构用户实现类  
@Component  
public class OrgUserImpl implements ReturnUser {  
    @Override  
    public List<String> getUserByType() {  
        // 业务逻辑  
        return Arrays.asList("org1", "org2", "org3");  
    }  
} 


// 角色用户实现类  
@Component  
public class RoleUserImpl implements ReturnUser {  
    @Override  
    public List<String> getUserByType() {  
        // 业务逻辑  
        return Arrays.asList("role1", "role2", "role3");  
    }  
} 
3. 创建工厂类

接下来,创建一个工厂类,用于生成具体类的实例。

复制代码
// 用户工厂类  
@Component  
public class ReturnUserFactory {  
    @Autowired  
    private OrgUserImpl orgUser;  
  
    @Autowired  
    private RoleUserImpl roleUser;  
  
    public ReturnUser getUserList(String module) {  
        switch (module) {  
            case "org":  
                return orgUser;  
            case "role":  
                return roleUser;  
            default:  
                return null;  
        }  
    }  
} 
4. 在Spring Boot中使用工厂类

你可以在你的Spring Boot应用程序中的任何地方使用工厂类来创建对象。例如,在一个控制器中:

复制代码
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RequestParam;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class ReturnUserController {  
  
    @GetMapping("/returnUser")  
    public String getAnimalSound(@RequestParam String type) {  
        ReturnUser returnUser  = AnimalFactory.getUserList(type);  
        if (returnUser != null) {  
            returnUser.makeSound();  
            return "The returnUser makes the sound: " + returnUser.makeSound();  
        } else {  
            return "Unknown returnUser type";  
        }  
    }  
}
3. 代理模式(Proxy Pattern)
1. 定义接口

首先,定义一个接口,这是被代理对象必须实现的。

复制代码
public interface Service {  
    void performTask();  
}
2. 实现接口

然后,创建一个实现该接口的具体类。

复制代码
public class RealService implements Service {  
    @Override  
    public void performTask() {  
        System.out.println("Performing real service task.");  
    }  
}
3. 创建代理类

接下来,创建一个代理类,它实现了相同的接口,并在调用实际对象的方法之前或之后添加额外的行为。

复制代码
public class ServiceProxy implements Service {  
    private final Service realService;  
  
    public ServiceProxy(Service realService) {  
        this.realService = realService;  
    }  
  
    @Override  
    public void performTask() {  
        System.out.println("Performing proxy task before real service.");  
        realService.performTask();  
        System.out.println("Performing proxy task after real service.");  
    }  
}
4. 在Spring Boot中使用代理

你可以在你的Spring Boot应用程序中的任何地方使用代理类。例如,在一个控制器中:

复制代码
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class ServiceController {  
  
    private final Service service;  
  
    // 你可以通过构造函数注入来传递代理对象,或者你可以直接在控制器中创建代理对象  
    public ServiceController(Service realService) {  
        this.service = new ServiceProxy(realService);  
    }  
  
    @GetMapping("/service")  
    public String getService() {  
        service.performTask();  
        return "Service task performed with proxy.";  
    }  
}

但是,请注意,在上面的例子中,我们并没有真正利用Spring的依赖注入来管理代理的创建。在实际应用中,你可能会希望Spring来管理这些代理对象。这可以通过使用Spring AOP(面向切面编程)来实现,它允许你在不修改源代码的情况下向现有对象添加行为。


代理模式为其他对象提供一种代理以控制对这个对象的访问。Spring AOP(面向切面编程)就是代理模式的一个应用。

复制代码
// 切面类  
@Aspect  
@Component  
public class MyAspect {  
  
    @Around("execution(* com.example.service.*.*(..))")  
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {  
        long start = System.currentTimeMillis();  
  
        Object proceed = joinPoint.proceed();  
  
        long executionTime = System.currentTimeMillis() - start;  
  
        System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");  
  
        return proceed;  
    }  
}
4. 观察者模式(Observer Pattern)

在Spring Boot中使用观察者模式(Observer Pattern)可以让你构建一个能够自动通知和更新依赖对象(观察者)的系统,当某个对象(主题)的状态发生变化时。Spring Boot中的事件监听机制就是观察者模式的一个应用。

1. 定义主题接口

首先,你需要定义一个主题接口,它包含添加、移除和通知观察者的方法。

复制代码
// Subject.java  
public interface Subject {  
    void registerObserver(Observer observer);  
    void removeObserver(Observer observer);  
    void notifyObservers();  
}
2. 实现具体的主题

接下来,实现一个具体的主题类,该类将维护一个观察者列表,并在状态变化时通知它们。

复制代码
// ConcreteSubject.java  
import java.util.ArrayList;  
import java.util.List;  
  
public class ConcreteSubject implements Subject {  
    private List<Observer> observers = new ArrayList<>();  
    private String state;  
  
    @Override  
    public void registerObserver(Observer observer) {  
        observers.add(observer);  
    }  
  
    @Override  
    public void removeObserver(Observer observer) {  
        observers.remove(observer);  
    }  
  
    @Override  
    public void notifyObservers() {  
        for (Observer observer : observers) {  
            observer.update(this);  
        }  
    }  
  
    public void setState(String state) {  
        this.state = state;  
        notifyObservers();  
    }  
  
    public String getState() {  
        return state;  
    }  
}
3. 定义观察者接口

然后,定义一个观察者接口,它包含一个更新方法,当主题状态变化时被调用。

复制代码
// Observer.java  
public interface Observer {  
    void update(Subject subject);  
}
4. 实现具体的观察者

实现具体的观察者类,这些类将响应主题的状态变化。

复制代码
// ConcreteObserver.java  
public class ConcreteObserver implements Observer {  
    private String name;  
  
    public ConcreteObserver(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public void update(Subject subject) {  
        ConcreteSubject concreteSubject = (ConcreteSubject) subject;  
        System.out.println(name + " received state update: " + concreteSubject.getState());  
    }  
}
5. 在Spring Boot应用中使用

最后,在Spring Boot应用中使用这些类。你可以通过配置类或直接在控制器、服务等组件中实例化它们。

复制代码
// ObserverPatternApplication.java  
import org.springframework.boot.CommandLineRunner;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
  
@SpringBootApplication  
public class ObserverPatternApplication implements CommandLineRunner {  
  
    public static void main(String[] args) {  
        SpringApplication.run(ObserverPatternApplication.class, args);  
    }  
  
    @Override  
    public void run(String... args) throws Exception {  
        ConcreteSubject subject = new ConcreteSubject();  
  
        Observer observer1 = new ConcreteObserver("Observer 1");  
        Observer observer2 = new ConcreteObserver("Observer 2");  
  
        subject.registerObserver(observer1);  
        subject.registerObserver(observer2);  
  
        subject.setState("New State");  
    }  
}

在这个示例中,ObserverPatternApplication是我们的Spring Boot应用主类。它创建了一个ConcreteSubject对象,并注册了两个ConcreteObserver对象。然后,它更改主题的状态,这将触发对观察者的通知。

5. 策略模式(Strategy Pattern)

策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互换。Spring Boot中可以通过接口和不同的实现类来实现策略模式。

复制代码
// 策略接口  
public interface PaymentStrategy {  
    void pay(double amount);  
}  
  
// 具体策略实现类:信用卡支付  
@Component  
public class CreditCardPayment implements PaymentStrategy {  
    @Override  
    public void pay(double amount) {  
        System.out.println("Paid " + amount + " using Credit Card");  
    }  
}  
  
// 具体策略实现类:现金支付  
@Component  
public class CashPayment implements PaymentStrategy {  
    @Override  
    public void pay(double amount) {  
        System.out.println("Paid " + amount + " using Cash");  
    }  
}  
  
// 上下文类  
@Component  
public class PaymentContext {  
  
    @Autowired  
    private List<PaymentStrategy> paymentStrategies;  
  
    public void setPaymentMethod(String method) {  
        this.paymentMethod = method;  
    }  
  
    public void pay(double amount) {  
        for (PaymentStrategy strategy : paymentStrategies) {  
            if (strategy.getClass().getSimpleName().equalsIgnoreCase(this.paymentMethod)) {  
                strategy.pay(amount);  
                break;  
            }  
        }  
    }  
  
    private String paymentMethod;  
}
6. 模板方法模式(Template Method Pattern)

在Spring Boot中使用模板方法模式(Template Method Pattern)通常涉及创建一个抽象基类,该类定义了一个算法的框架,但将某些步骤的实现留给子类。这样,你可以在不改变算法结构的情况下,通过定义新的子类来改变算法中的某些步骤。

1. 定义抽象基类

首先,你需要创建一个抽象基类,其中包含一个模板方法(通常是final的,以防止子类覆盖它)和一些抽象方法(或钩子方法,这些可以是具体实现,但允许子类根据需要覆盖它们)。

复制代码
// AbstractClass.java  
public abstract class AbstractClass {  
  
    // 模板方法,定义了算法的框架  
    public final void templateMethod() {  
        step1();  
        step2();  
        hookMethod(); // 钩子方法,允许子类在必要时提供自己的实现  
        step3();  
    }  
  
    // 抽象方法,由子类实现  
    protected abstract void step1();  
    protected abstract void step3();  
  
    // 钩子方法,有默认实现,但允许子类覆盖  
    protected void hookMethod() {  
        // 默认实现为空,或者提供一些通用的行为  
    }  
  
    // 具体方法,可以包含一些算法的通用步骤  
    private void step2() {  
        // 这里是算法的一个具体步骤,通常不需要子类覆盖  
    }  
}
2. 实现具体子类

然后,你需要创建具体子类,这些子类将提供模板方法中抽象方法和钩子方法的具体实现。

复制代码
// ConcreteClassA.java  
public class ConcreteClassA extends AbstractClass {  
  
    @Override  
    protected void step1() {  
        System.out.println("ConcreteClassA implementation of step1");  
    }  
  
    @Override  
    protected void step3() {  
        System.out.println("ConcreteClassA implementation of step3");  
    }  
  
    // 可以选择覆盖钩子方法以提供额外的行为  
    // @Override  
    // protected void hookMethod() {  
    //     System.out.println("ConcreteClassA implementation of hookMethod");  
    // }  
}  
  
// ConcreteClassB.java  
public class ConcreteClassB extends AbstractClass {  
  
    @Override  
    protected void step1() {  
        System.out.println("ConcreteClassB implementation of step1");  
    }  
  
    @Override  
    protected void step3() {  
        System.out.println("ConcreteClassB implementation of step3");  
    }  
  
    // 覆盖钩子方法以提供不同的行为  
    @Override  
    protected void hookMethod() {  
        System.out.println("ConcreteClassB implementation of hookMethod");  
    }  
}
3. 在Spring Boot应用中使用

最后,在你的Spring Boot应用中,你可以像使用任何其他Spring Bean一样使用这些具体子类。你可以通过配置类、@Component注解或直接在控制器、服务等组件中实例化它们。

复制代码
// TemplateMethodPatternApplication.java  
import org.springframework.boot.CommandLineRunner;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
  
@SpringBootApplication  
public class TemplateMethodPatternApplication implements CommandLineRunner {  
  
    public static void main(String[] args) {  
        SpringApplication.run(TemplateMethodPatternApplication.class, args);  
    }  
  
    @Override  
    public void run(String... args) throws Exception {  
        AbstractClass concreteClassA = new ConcreteClassA();  
        AbstractClass concreteClassB = new ConcreteClassB();  
  
        // 调用模板方法  
        concreteClassA.templateMethod();  
        concreteClassB.templateMethod();  
    }  
}

在这个示例中,TemplateMethodPatternApplication是我们的Spring Boot应用主类。它创建了两个具体子类的实例,并调用了它们的模板方法。这将按照算法框架执行,并使用子类提供的具体实现。

请注意,虽然在这个例子中我们没有将AbstractClass及其子类作为Spring Bean来管理,但在实际的应用中,你可能会希望这样做以便利用Spring的依赖注入功能。你可以通过添加@Component注解并使用@Autowired@Bean注解来将这些类集成到Spring的上下文中。

7. 适配器模式(Adapter Pattern)

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的类一起工作。在Spring Boot应用中,你可以使用适配器模式来适配不同接口或类的实现,以便它们可以无缝地协同工作。

下面是一个如何在Spring Boot中使用适配器模式的示例。

假设我们有一个旧的支付服务(LegacyPaymentService),它的接口和新支付服务(NewPaymentService)的接口不兼容。我们需要一个适配器来使它们可以一起工作。

1. 定义旧的支付服务接口和实现

首先,我们定义一个旧的支付服务接口及其实现:

复制代码
// LegacyPaymentService.java  
public interface LegacyPaymentService {  
    void makeLegacyPayment(double amount);  
}  
  
// LegacyPaymentServiceImpl.java  
public class LegacyPaymentServiceImpl implements LegacyPaymentService {  
    @Override  
    public void makeLegacyPayment(double amount) {  
        System.out.println("Making legacy payment of: " + amount);  
    }  
}
2. 定义新的支付服务接口和实现

接下来,我们定义一个新的支付服务接口及其实现:

复制代码
// NewPaymentService.java  
public interface NewPaymentService {  
    void makePayment(double amount);  
}  
  
// NewPaymentServiceImpl.java  
public class NewPaymentServiceImpl implements NewPaymentService {  
    @Override  
    public void makePayment(double amount) {  
        System.out.println("Making new payment of: " + amount);  
    }  
}
3. 创建适配器类

现在,我们需要创建一个适配器类,它将旧的支付服务适配为新的支付服务:

复制代码
// LegacyPaymentServiceAdapter.java  
public class LegacyPaymentServiceAdapter implements NewPaymentService {  
    private LegacyPaymentService legacyPaymentService;  
  
    public LegacyPaymentServiceAdapter(LegacyPaymentService legacyPaymentService) {  
        this.legacyPaymentService = legacyPaymentService;  
    }  
  
    @Override  
    public void makePayment(double amount) {  
        legacyPaymentService.makeLegacyPayment(amount);  
    }  
}
4. 使用Spring Boot配置和测试

最后,我们在Spring Boot应用中配置这些类并进行测试。

复制代码
import org.springframework.boot.CommandLineRunner;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.context.annotation.Bean;  
  
@SpringBootApplication  
public class PaymentServiceApplication implements CommandLineRunner {  
  
    public static void main(String[] args) {  
        SpringApplication.run(PaymentServiceApplication.class, args);  
    }  
  
    @Bean  
    public LegacyPaymentService legacyPaymentService() {  
        return new LegacyPaymentServiceImpl();  
    }  
  
    @Bean  
    public NewPaymentService newPaymentService(LegacyPaymentService legacyPaymentService) {  
        return new LegacyPaymentServiceAdapter(legacyPaymentService);  
    }  
  
    @Override  
    public void run(String... args) throws Exception {  
        NewPaymentService paymentService = newPaymentService();  
        paymentService.makePayment(100.0);  
    }  
}

在这个示例中,PaymentServiceApplication类是我们的Spring Boot应用主类。它定义了两个Bean:legacyPaymentServicenewPaymentServicenewPaymentService是通过LegacyPaymentServiceAdapter适配的legacyPaymentService

当运行Spring Boot应用时,run方法会被调用,并且适配器会将新的支付请求转换为旧的支付请求,并输出相应的日志。

8. 装饰者模式(Decorator Pattern)

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将责任附加到对象上,而无需修改其现有的代码。在Spring Boot应用中,你可以使用装饰者模式来增强或修改对象的行为,而无需使用继承或创建大量的子类。

1. 定义组件接口

首先,我们定义一个接口,该接口将作为要装饰的对象的基类或接口。

复制代码
// PaymentComponent.java  
public interface PaymentComponent {  
    void pay(double amount);  
}
2. 实现基础组件

接下来,我们实现这个接口的基础版本,即不添加任何装饰的组件。

复制代码
// SimplePayment.java  
public class SimplePayment implements PaymentComponent {  
    @Override  
    public void pay(double amount) {  
        System.out.println("Paid: " + amount);  
    }  
}
3. 创建装饰者基类

现在,我们创建一个装饰者基类,它实现了相同的接口,并持有一个被装饰对象的引用。

复制代码
// PaymentDecorator.java  
public abstract class PaymentDecorator implements PaymentComponent {  
    protected PaymentComponent paymentComponent;  
  
    public PaymentDecorator(PaymentComponent paymentComponent) {  
        this.paymentComponent = paymentComponent;  
    }  
  
    @Override  
    public abstract void pay(double amount);  
}
4. 实现具体的装饰者

然后,我们实现具体的装饰者,这些装饰者将添加额外的行为或修改现有行为。

复制代码
// LoggingPaymentDecorator.java  
public class LoggingPaymentDecorator extends PaymentDecorator {  
    public LoggingPaymentDecorator(PaymentComponent paymentComponent) {  
        super(paymentComponent);  
    }  
  
    @Override  
    public void pay(double amount) {  
        System.out.println("Logging payment of: " + amount);  
        paymentComponent.pay(amount);  
    }  
}  
  
// TaxPaymentDecorator.java  
public class TaxPaymentDecorator extends PaymentDecorator {  
    private double taxRate;  
  
    public TaxPaymentDecorator(PaymentComponent paymentComponent, double taxRate) {  
        super(paymentComponent);  
        this.taxRate = taxRate;  
    }  
  
    @Override  
    public void pay(double amount) {  
        double totalAmount = amount * (1 + taxRate);  
        System.out.println("Applying tax rate of " + (taxRate * 100) + "%");  
        paymentComponent.pay(totalAmount);  
    }  
}
5. 使用Spring Boot配置和测试

最后,我们在Spring Boot应用中配置这些类并进行测试。

复制代码
// PaymentServiceApplication.java  
import org.springframework.boot.CommandLineRunner;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.context.annotation.Bean;  
  
@SpringBootApplication  
public class PaymentServiceApplication implements CommandLineRunner {  
  
    public static void main(String[] args) {  
        SpringApplication.run(PaymentServiceApplication.class, args);  
    }  
  
    @Bean  
    public PaymentComponent simplePayment() {  
        return new SimplePayment();  
    }  
  
    @Bean  
    public PaymentComponent decoratedPayment(PaymentComponent simplePayment, double taxRate) {  
        PaymentComponent loggingPayment = new LoggingPaymentDecorator(simplePayment);  
        return new TaxPaymentDecorator(loggingPayment, taxRate);  
    }  
  
    @Override  
    public void run(String... args) throws Exception {  
        PaymentComponent paymentComponent = decoratedPayment(simplePayment(), 0.10); // 10% tax rate  
        paymentComponent.pay(100.0);  
    }  
}

在这个示例中,PaymentServiceApplication类是我们的Spring Boot应用主类。它定义了两个Bean:simplePaymentdecoratedPaymentdecoratedPayment是通过组合LoggingPaymentDecoratorTaxPaymentDecorator来装饰simplePayment的。

然而,需要注意的是,在Spring容器中直接这样配置decoratedPaymentBean可能会有些复杂,因为我们需要传递一个double类型的taxRate参数。在实际应用中,你可能会使用配置属性、环境变量或其他方式来传递这个参数。

为了简化示例,这里直接在run方法中创建了装饰后的对象。但在实际生产环境中,你应该通过配置或注入的方式来管理这些Bean的依赖关系。

9. 原型模式(Prototype Pattern)

原型模式用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。在Spring中,可以通过实现PrototypeBeanFactory来创建原型Bean。

复制代码
// 原型Bean类  
public class PrototypeBean implements Cloneable {  
    private String name;  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    @Override  
    protected Object clone() throws CloneNotSupportedException {  
        return super.clone();  
    }  
}  
  
// 配置类  
@Configuration  
public class AppConfig {  
    @Bean  
    @Scope("prototype")  
    public PrototypeBean prototypeBean() {  
        return new PrototypeBean();  
    }  
}
相关推荐
JIngJaneIL11 分钟前
健身管理小程序|基于java微信开发健身管理小程序的系统设计与实现(源码+数据库+文档)
java·数据库·小程序·vue·毕业设计·论文·健身管理小程序
菠萝崽.27 分钟前
springboot中测试python脚本:ProcessBuilder
java·开发语言·spring boot·python·processbuilder
哪吒编程42 分钟前
从0.031秒优化0.018秒,JEP 483为Java应用带来的启动加速黑科技
java·后端
努力的搬砖人.1 小时前
nacos配置达梦数据库驱动源代码步骤
java·服务器·数据库·经验分享·后端
朱啸毅1 小时前
Tomcat
java·tomcat
风象南1 小时前
SpringBoot中3种条件装配技术
java·spring boot·后端
Java小白中的菜鸟1 小时前
深入理解Java反射
java·开发语言
自由与自然1 小时前
乐观锁与悲观锁的使用场景
java·服务器·数据库
呆萌很1 小时前
基于 Spring Boot 瑞吉外卖系统开发(三)
spring boot
爱的叹息4 小时前
spring mvc 中 RestTemplate 全面详解及示例
java·spring·mvc