工厂模式、单例模式、装饰模式、策略模式、代理模式和观察者模式

1.工厂模式

实际应用场景

工厂方法在SpringBoot中,如果在用工厂的同时又出现了new,那绝对是一个败笔。在SpringBoot中,几乎所有对象都可以直接交给Spring容器管理,它天然已经是一个工厂对象,因此在SpringBoot项目中用工厂模式,再频繁new对象反而不妥。那么工厂模式究竟怎么用在SpringBoot项目的支付场景呢?其实很简单,如果我们要选择一个支付渠道,而项目中有100种支付渠道,那这个时候无疑要写100个@Autowired 注入100个支付渠道,并且需要做100种判断,这个时候我们可以用工厂模式取代我们判断,直接根据我们配置的映射关系从Spring容器中拿到对应支付渠道的实例,代码量将大大减少,这块是使用工厂的另一种秒用。

模拟场景

工厂方法模式包含如下角色:

  • Product:抽象产品
  • ConcreteProduct:具体产品
  • Factory:抽象工厂
  • ConcreteFactory:具体工厂

结构图:

image-20231222165932962

时序图

image-20231222170008739

工厂模式总结

(1)适用场景

输出的产品是标准品,谁来做都可以。

(2)举例

常见的数据库连接工厂,SqlSessionFactory,产品是一个数据库连接,至于是oracle提供的,还是mysql提供的,我并不需要关心,因为都能让我通过sql来操作数据。

(3)注意事项

项目初期,软件结构和需求都没有稳定下来时,不建议使用此模式,因为其劣势也很明显,增加了代码的复杂度,增加了调用层次,增加了内存负担。所以要注意防止模式的滥用。

(4)简单实现

public class FactoryPatternDemo {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactoryB();
        Product product = factory.createProduct();
        product.use();
    }
}
//抽象产品:提供了产品的接口
interface Product
{
    public void use;
}
//具体产品A:实现抽象产品中的抽象方法
class ConcreteProductA implements Product
{
    public void use()
{
        System.out.println("具体产品A显示...");
    }
}

//具体产品B:实现抽象产品中的抽象方法
class ConcreteProductB implements Product
{
    public void use()
{
        System.out.println("具体产品B显示...");
    }
}

//抽象工厂:提供了厂品的生成方法
interface Factory
{
    public Product createProduct();
}

//具体工厂A:实现了厂品的生成方法
class ConcreteFactoryA implements AbstractFactory
{
    public Product createProduct()
{
        System.out.println("具体工厂A生成-->具体产品A.");
        return new ConcreteProductA();
    }
}

//具体工厂B:实现了厂品的生成方法
class ConcreteFactoryB implements AbstractFactory
{
    public Product createProduct()
{
        System.out.println("具体工厂B生成-->具体产品B.");
        return new ConcreteProductB();
    }
}

实际场景,在springboot中需要根据不同的情况使用不同的支付方式

工厂

@Data
@Configuration
public class PayFactory implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        PayFactory.applicationContext = applicationContext;
    }

    //根据不同的key获取到不同的bean,从而实现不同的支付方式
    public PayChannel createChannel(String key) {
        return applicationContext.getBean(key, PayChannel.class);
    }
}
public interface PayChannel {
    void pay();
}


@Component("weixinPay")
public class WeixinPay implements PayChannel {
    @Override
    public void pay() {
        System.out.println("微信支付");
    }
}


@Component("aliPay")
public class AliPay implements PayChannel {
    @Override
    public void pay() {
        System.out.println("支付宝支付");
    }
}


@RestController
public class PayController {

    @Autowired
    private PayFactory payFactory;


    @GetMapping("/pay")
    public void pay(){
        PayChannel channel = payFactory.createChannel("1");
        channel.pay();
    }

}

2.单例模式

概念:

什么是单例模式?

单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供全局访问点来获取该实例。简单来说,单例模式就是通过限制类的实例化次数,使得该类只能被实例化一次。

在单例模式中,类的构造方法通常会被设置为私有,以防止外部直接创建该类的实例。同时,该类内部会定义一个静态方法或成员变量来获取唯一的实例。

单例模式的主要目的是确保系统中只存在一个实例,这样可以节省资源并提高性能。常见的应用场景包括数据库连接池、线程池、日志记录器等需要全局访问且实例唯一的情况。

经典的单例模式实现方式是懒汉式和饿汉式。懒汉式在首次使用时才创建实例,而饿汉式在类加载时就创建实例。懒汉式相对于饿汉式更加延迟实例化,但需要考虑多线程下的线程安全性。

优点:

  1. 独一无二的实例:通过单例模式,确保一个类只有一个实例存在。这可以避免不同部分的代码创建出多个相同的实例,保证实例的唯一性。
  2. 全局访问点:单例模式提供了一个全局的访问点,使得其他对象可以方便地获取到该单例实例。这简化了对象之间的通信和数据共享。
  3. 节约资源:由于单例模式只创建一个实例并重复使用,可以减少系统中相同对象的创建和销毁过程,从而节约了系统资源。
  4. 惰性实例化:懒汉式单例模式在首次使用时才创建实例,避免了不必要的资源浪费。当实例对象较为复杂或初始化耗时较长时,惰性实例化可以提升系统启动速度。
  5. 避免竞态条件:单例模式可以通过合适的实现方式(如双重检查锁定)避免多线程下的竞态条件,确保线程安全性。
  6. 可控的实例化:通过单例模式,可以对实例化过程进行集中控制,从而更好地管理和维护实例化对象。

1.springboot单例模式

在Spring Boot中实现单例模式,可以使用Spring框架提供的**@Scope**注解。默认情况下,Spring Bean是单例的,因此不需要显式地指定@Scope注解。但是,如果需要更改Bean的作用域,则可以使用@Scope注解。

以下是一个使用@Scope注解实现单例模式的示例:

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class SingletonBean {
    // 单例Bean的代码
}

在上面的示例中,我们使用@Component注解将SingletonBean类标记为Spring Bean,并使用@Scope(“singleton”)注解将其作用域设置为单例。

相关问题

2.springboot启用单例模式

在SpringBoot中,默认情况下,所有的Bean都是以单例模式进行管理的。这意味着在应用程序的整个生命周期中,只会创建一个实例,并且该实例会在需要时被重复使用。

SpringBoot中启用单例模式的方式有以下几种:

  1. 默认方式:当使用@Component@Service@Repository等注解标记类时,默认情况下会以单例模式进行管理。
@Service
public class UserService {
    // ...
}
  1. 使用@Scope注解:通过在类级别上使用@Scope("singleton")注解,可以明确指定该类以单例模式进行管理。
@Service
@Scope("singleton")
public class UserService {
    // ...
}
  1. 在配置文件中指定:可以在application.propertiesapplication.yml配置文件中,设置spring.main.allow-bean-definition-overriding=true来启用单例模式。这样,在使用@Component@Service@Repository等注解标记类时,默认会以单例模式进行管理。

需要注意的是,即使启用了单例模式,SpringBoot仍然可以通过其他方式创建非单例的Bean,例如在方法上使用@Scope("prototype")注解来指定原型模式。此外,在多线程环境下,需要注意单例Bean的线程安全性。

3.springboot怎么使用单例模式

在Spring Boot中使用单例模式与使用传统的Java应用程序中使用单例模式是相同的。单例模式是一种创建型设计模式,旨在确保类只有一个实例,并且提供一个全局访问点。在Spring Boot中,可以通过将类标记为组件(使用@Component或其他相关注释)来实现单例模式,Spring Boot会自动管理这些组件的生命周期。

例如,考虑一个名为SingletonService的类,它使用单例模式实现:

@Component
public class SingletonService {
    private static SingletonService instance;

    private SingletonService() {}

    public static synchronized SingletonService getInstance() {
        if (instance == null) {
            instance = new SingletonService();
        }
        return instance;
    }

    public void doSomething() {
        System.out.println("Doing something...");
    }
}

该示例通过在getInstance方法上添加synchronized关键字确保线程安全,但会对性能造成一定影响。为了避免每次都进行同步,也可以采用双重检查锁定(Double-Checked Locking)或静态内部类的方式实现懒汉式单例模式。

@Service
public class MyService {
    @Autowired
    private SingletonService singletonService;

    public void doSomething() {
        singletonService.doSomething();
    }
}

这样做可以确保在应用程序中只有一个SingletonService实例,并且可以在需要时被注入到其他组件中使用。

3.装饰模式

装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

装饰器模式的主要优点有:

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则

其主要缺点是:装饰器模式会增加许多子类,过度使用会增加程序得复杂性。

1. 装饰器模式的结构与实现

通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰器模式的目标。下面来分析其基本结构和实现方法

4.建造者模式

4.1结构

  • 抽象建造者
  • 具体建造者
  • 产品类
  • 指挥者类