Spring中的适配器模式和策略模式

1. 适配器模式的应用

1.1适配器模式(Adapter Pattern)的原始定义是:将一个类的接口转换为客户期望的另一个接口,适配器可以让不兼容的两个类一起协同工作。

在这里插入图片描述

1.2 AOP中的适配器模式

在Spring的AOP中,使用Advice(通知)来增强被代理类的功能。Advice的类型有:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice。每种Advice都有对应的拦截器,如MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。

在这里插入图片描述

1.3 代码示例

以下示例展示了如何使用适配器模式在Spring AOP中增强一个目标类的功能。

public interface MyService {
    void doSomething();
}

public class MyServiceImpl implements MyService {
    @Override
    public void doSomething() {
        System.out.println("Doing something ...");
    }
}

// 使用Advice(通知)来增强被代理类的功能
public class MyBeforeAdvice implements MethodBeforeAdvice {
    // 在目标方法执行前进行拦截
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("我变强,也变秃了......");
    }
}

// 自定义适配器对象,将BeforeAdvice对象适配为一个MethodBeforeAdviceInterceptor对象
public class MyBeforeAdviceAdapter extends MethodBeforeAdviceInterceptor {
    public MyBeforeAdviceAdapter(MethodBeforeAdvice advice) {
        super(advice);
    }
}

public class Test01 {
    public static void main(String[] args) {
        // 创建前置通知对象
        MyBeforeAdvice advice = new MyBeforeAdvice();
        // 创建适配器对象,传入通知对象
        MyBeforeAdviceAdapter adapter = new MyBeforeAdviceAdapter(advice);
        // 获取目标对象的代理工厂
        ProxyFactory factory = new ProxyFactory(new MyServiceImpl());
        // 向代理对象中添加适配器对象
        factory.addAdvice(adapter);
        // 获取代理对象
        MyService proxy = (MyService) factory.getProxy();
        // 调用代理方法
        proxy.doSomething();
    }
}

每个类对应适配器模式中的如下角色:

  1. TargetMyServiceImpl类是目标对象,即需要被代理的对象。
  2. AdapterMyBeforeAdviceAdapter类是适配器对象,它将 MyBeforeAdvice对象适配为一个 MethodBeforeAdviceInterceptor对象,使得 MyBeforeAdvice可以被应用到目标对象的代理中。
  3. AdapteeMyBeforeAdvice类是被适配的对象,它定义了一个前置通知方法,在目标方法执行前进行拦截。
  4. ClientTest01类是客户端,它通过创建适配器对象并将其添加到目标对象的代理中,实现了在目标方法执行前应用 MyBeforeAdvice的前置通知。
    在这里插入图片描述

2. 策略模式的应用

策略模式是一种行为设计模式,它允许定义一系列算法,将每个算法分别封装起来,并使它们可以相互替换。这种模式使得算法可以在不影响客户端的情况下发生变化。在Spring框架中,策略模式的应用十分广泛,下面是Resource接口及其实现类的示例。

2.1 Resource 接口

Spring框架的资源访问Resource接口提供了强大的资源访问能力。Spring框架本身大量使用了Resource接口来访问底层资源。Resource接口本身没有提供访问任何底层资源的实现逻辑,而是针对不同的底层资源提供了不同的Resource实现类,这些实现类负责不同的资源访问逻辑。

Spring为Resource接口提供了如下实现类:

  • UrlResource:访问网络资源的实现类。
  • ClassPathResource:访问类加载路径里的资源的实现类。
  • FileSystemResource:访问文件系统里的资源的实现类。
  • ServletContextResource:访问相对于ServletContext路径里的资源的实现类。
  • InputStreamResource:访问输入流资源的实现类。
  • ByteArrayResource:访问字节数组资源的实现类。

这些Resource实现类针对不同的底层资源提供了相应的资源访问逻辑,并提供便捷的包装,以便客户端程序的资源访问。

public class ResourceTest {

    public static void main(String[] args) throws IOException {
        // 创建ClassPathResource对象
        Resource resource = new ClassPathResource("application.properties");

        // 调用getInputStream()方法读取资源
        InputStream is = resource.getInputStream();

        byte[] bytes = new byte[1024];
        int n;
        while ((n = is.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, n));
        }
        is.close();
    }
}

2.2 DefaultResourceLoader

ResourceLoader接口用于返回Resource对象,其实现可以看作是一个生产Resource的工厂类。当创建Resource对象时,Spring会根据传入的资源路径来选择相应的Resource实现类。这一过程是由Spring中的ResourceLoader接口及其实现类DefaultResourceLoader来完成的。

DefaultResourceLoader中的getResource方法会根据传入的资源路径选择相应的Resource实现类,从而实现了策略模式的效果。

public Resource getResource(String location) {
    Assert.notNull(location, "Location must not be null");

    // 遍历ProtocolResolver集合,通过ProtocolResolver来解析资源路径
    for (ProtocolResolver protocolResolver : this.getProtocolResolvers()) {
        Resource resource = protocolResolver.resolve(location, this);
        if (resource != null) {
            return resource;
        }
    }

    // 没有找到对应的ProtocolResolver,使用默认的处理方式
    if (location.startsWith("/")) {
        // 以斜杠开头的路径,表示基于ServletContext的相对路径
        return this.getResourceByPath(location);
    } else if (location.startsWith("classpath:")) {
        // 以classpath:开头的路径,表示在classpath下查找资源
        return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
    } else {
        try {
            // 尝试将路径解析为URL,如果是文件URL则创建FileUrlResource,否则创建UrlResource
            URL url = new URL(location);
            return (Resource) (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
        } catch (MalformedURLException var5) {
            // 如果路径无法解析为URL,则当做相对路径来处理
            return this.getResourceByPath(location);
        }
    }
}

在上述代码中,getResource方法根据传入的资源路径选择相应的Resource实现类,从而实现了策略模式的效果。不同的实现类负责不同类型资源的访问逻辑,使得Resource接口的使用更加灵活和便捷。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
适配器模式Spring有多个体现。 首先,Spring框架的JdbcTemplate类就是一个适配器模式的实例。JdbcTemplate类充当了数据库操作的适配器,在底层直接与数据库交互,屏蔽了底层数据库的差异性,提供了一个统一的接口供上层应用程序进行数据库操作。这样一来,开发人员可以通过使用JdbcTemplate类,无须关心具体数据库的细节,可以方便地在不同数据库之间切换。 其次,Spring提供了MessageListenerAdapter类来支持消息的适配。当我们需要处理不同类型的消息时,可以实现不同的消息处理类,然后通过MessageListenerAdapter类来将消息适配到正确的处理类上。这样,我们就可以通过统一的接口来处理不同类型的消息,提高了代码的可维护性和灵活性。 另外,Spring的MVC框架也使用了适配器模式。MVC框架将请求的处理交给Controller来处理,而Controller实际上是一个适配器,负责将请求进行适配,然后调用具体的处理器来处理请求。通过使用适配器模式Spring的MVC框架可以支持多种不同类型的处理器,无须修改框架的核心代码,提供了灵活性和可扩展性。 总结来说,适配器模式Spring的体现主要包括数据库操作的适配、消息处理的适配以及请求处理的适配等方面。通过使用适配器模式Spring提供了一种解耦的方式,将底层的实现和上层的应用程序分离开来,提高了代码的可维护性、灵活性和扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖的小熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值