不爱吃鸭脖 不爱吃鸭脖
首页
Java
算法
k8s
日常
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

不爱吃鸭脖

小学生
首页
Java
算法
k8s
日常
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • java基础

  • 并发编程

  • java虚拟机

  • Spring

  • Redis

  • MySQL

  • 网络

  • 操作系统

  • 消息队列

  • 设计模式

    • Spring中的设计模式
      • 设计原则
      • 设计模式
        • 工厂方法模式
        • 代理模式
        • 单例模式
        • 装饰器模式
        • 适配器模式
        • 观察者模式
        • 策略模式
        • 模板方法模式
  • Linux

  • git

  • Mybatis

  • Java
  • 设计模式
jinhua
2023-07-25
目录

Spring中的设计模式

# 设计原则

设计模式中有七大原则,它们分别是:

  1. 开闭原则(Open Closed Principle,OCP)
  2. 单一职责原则(Single Responsibility Principle, SRP)
  3. 里氏代换原则(Liskov Substitution Principle,LSP)
  4. 依赖倒转原则(Dependency Inversion Principle,DIP)
  5. 接口隔离原则(Interface Segregation Principle,ISP)
  6. 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
  7. 最少知识原则(Least Knowledge Principle,LKP)或者迪米特法则(Law of Demeter,LOD)¹。

这些原则的目的是降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性

  • 开闭原则:比如您有一个生产电脑的工厂类,根据输入的类型,生产出不同的电脑。如果您需要添加新的电脑产品,那么修改工厂类的方法会违反开闭原则,因为您修改了已有的代码。正确的做法应该是将工厂类抽象成接口,让具体的工厂类去实现它,生产它们公司相应的产品。
  • 单一职责原则:比如您有一个动物类,它会呼吸空气。如果您需要添加新的功能,比如鱼需要呼吸水,那么修改动物类的方法会违反单一职责原则,因为您让一个类负责了两个不同的职责。正确的做法应该是将动物类分解为陆生动物类和水生动物类。
  • 里氏代换原则:比如您有一个书籍类,它有一个获取内容的方法。如果您需要添加新的功能,比如漫画类,它也有一个获取内容的方法,但是返回的是图片而不是文字。那么使用漫画类替换书籍类会违反里氏代换原则,因为您改变了父类方法预期的行为。正确的做法应该是将书籍类和漫画类分别继承一个抽象的媒体类。
  • 依赖倒转原则:比如您有一个业务逻辑类,它需要操作数据库。如果您直接依赖于具体的数据库操作类,那么当数据库发生变化时,您需要修改业务逻辑类的代码。这样会违反依赖倒转原则,因为您让高层模块依赖于低层模块。正确的做法应该是让业务逻辑类依赖于一个抽象的数据库操作接口,让具体的数据库操作类去实现它。
  • 接口隔离原则:比如您有一个动物接口,它定义了吃、喝、跑、飞等方法。如果您让狗实现这个接口,那么狗就必须实现飞这个方法,即使它不会飞。这样会违反接口隔离原则,因为您让一个类依赖于它不需要的方法。正确的做法应该是将动物接口分解为多个更小更专业的接口。
  • 合成/聚合复用原则:比如您有一个汽车类和一个轮胎类。如果您让汽车继承轮胎,那么当轮胎发生变化时,汽车也需要跟着变化。这样会违反合成/聚合复用原则,因为您使用了继承来复用轮胎的功能。正确的做法应该是让汽车包含轮胎作为它的属性。
  • 最少知识原则:比如您有一个顾客类和一个商店类。如果顾客想要买东西,他就需要知道商店里有什么商品、商品有什么价格、商店有什么优惠活动等等。这样会违反最少知识原则,因为您让一个对象知道了太多其他对象的细节。正确的做法应该是让顾客只知道商店有一个购买方法,让商店内部处理其他的逻辑。

# 设计模式

  • 创建型模式:工厂方法模式、单例模式
  • 结构型模式:适配器模式、装饰器模式、代理模式
  • 行为型模式:观察者模式、策略模式、模板方法模式

# 工厂方法模式

Spring框架中的工厂方法模式体现在它使用BeanFactory和ApplicationContext来创建对象。这些工厂类可以根据配置文件或注解来创建和管理Bean对象。例如,下面是一个简单的例子,它演示了如何使用ApplicationContext来创建一个Bean对象:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
   }
}
1
2
3
4
5
6
7
8
9
10

在上面的例子中,我们使用ClassPathXmlApplicationContext来创建一个ApplicationContext实例,然后使用getBean方法从容器中获取一个名为"helloWorld"的Bean对象。这个Bean对象是根据Beans.xml配置文件中定义的Bean信息来创建的。

# 代理模式

Spring框架中的代理模式主要体现在它的AOP(面向切面编程)功能。Spring AOP使用代理模式来创建目标对象的代理,以便在目标方法执行前后添加额外的逻辑。Spring AOP可以使用JDK动态代理或CGLIB来创建代理对象。如果目标对象实现了接口,Spring AOP会使用JDK动态代理;否则,它会使用CGLIB来创建代理对象¹³。

例如,下面是一个简单的例子,它演示了如何使用Spring AOP来为目标方法添加前置通知:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyAspect {
    @Before("execution(* com.example.MyClass.myMethod(..))")
    public void beforeMyMethod() {
        System.out.println("Before myMethod");
    }
}
1
2
3
4
5
6
7
8
9
10

在上面的例子中,我们定义了一个切面类MyAspect,并在其中定义了一个前置通知方法beforeMyMethod。这个方法使用@Before注解来指定它应该在哪些方法执行之前执行。在这个例子中,我们指定beforeMyMethod应该在com.example.MyClass类中的myMethod方法执行之前执行。

# 单例模式

其中单例模式

# 装饰器模式

Spring框架中使用了装饰器模式来动态地给某些类增加一些额外的功能。在Spring中,使用装饰器模式的类通常具有两个典型的特征:一个是类名中含有Wrapper,另一个是类名中含有Decorator。

例如,Spring框架中的BufferedInputStream类就是一个装饰器类,它继承自FilterInputStream并实现了InputStream接口。它的作用是为另一个输入流添加缓冲功能,以提高读取性能。

# 适配器模式

Spring框架中使用了适配器模式来将不同类型的处理器(如Controller、HttpRequestHandler或者Servlet等)适配到统一的请求处理流程中。在Spring MVC中,这个功能是由HandlerAdapter接口及其实现类来完成的¹³。

例如,下面是一个简单的例子,它演示了如何使用HandlerAdapter接口来定义一个自定义的适配器:

import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof MyHandler;
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        MyHandler myHandler = (MyHandler) handler;
        myHandler.handleRequest(request, response);
        return null;
    }

    @Override
    public long getLastModified(HttpServletRequest request, Object handler) {
        return -1;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

在上面的例子中,我们定义了一个自定义的HandlerAdapter实现类MyHandlerAdapter。这个类实现了HandlerAdapter接口中的三个方法:supports、handle和getLastModified。其中,supports方法用于判断这个适配器是否支持给定的处理器类型;handle方法用于处理请求并返回一个ModelAndView对象;而getLastModified方法用于返回资源的最后修改时间。

# 观察者模式

Spring框架中使用了观察者模式来实现事件驱动模型。在Spring中,观察者模式由三部分组成:事件(ApplicationEvent)、事件发布者(ApplicationEventPublisher)和事件订阅者(ApplicationListener)。

例如,下面是一个简单的例子,它演示了如何在Spring中使用观察者模式来定义一个自定义事件:

import org.springframework.context.ApplicationEvent;

public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
    }
}
1
2
3
4
5
6
7

在Spring中,您可以通过实现ApplicationListener接口或使用@EventListener注解来监听自定义事件。

例如,下面是一个简单的例子,它演示了如何使用ApplicationListener接口来监听一个自定义事件:

import org.springframework.context.ApplicationListener;

public class MyEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        // 处理事件
    }
}
1
2
3
4
5
6
7
8

在上面的例子中,我们定义了一个自定义的事件监听器类MyEventListener,它实现了ApplicationListener接口。这个类重写了onApplicationEvent方法,用于处理MyEvent类型的事件。

另外,您也可以使用@EventListener注解来监听自定义事件,如下所示:

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventListener {
    @EventListener
    public void handleMyEvent(MyEvent event) {
        // 处理事件
    }
}
1
2
3
4
5
6
7
8
9
10

在上面的例子中,我们定义了一个名为MyEventListener的类,并在其中定义了一个名为handleMyEvent的方法。这个方法使用了@EventListener注解来指定它应该监听哪种类型的事件。在这个例子中,我们指定这个方法应该监听MyEvent类型的事件。

# 策略模式

Spring框架中使用了策略模式来支持不同的算法或行为的选择。在Spring中,您可以使用依赖注入特性来注入一个接口的多个实现,从而实现策略模式的选择。

例如,下面是一个简单的例子,它演示了如何在Spring中使用策略模式来定义一个策略接口及其多个实现:

public interface MyStrategy {
    void doSomething();
}

@Component
public class MyStrategyA implements MyStrategy {
    @Override
    public void doSomething() {
        // 实现A
    }
}

@Component
public class MyStrategyB implements MyStrategy {
    @Override
    public void doSomething() {
        // 实现B
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在上面的例子中,我们定义了一个策略接口MyStrategy,以及两个实现类MyStrategyA和MyStrategyB。这两个实现类都使用了@Component注解,因此它们会被Spring容器自动扫描并注册为Bean。

# 模板方法模式

Spring框架中使用了模板方法模式来封装不变的部分,扩展可变的部分。在Spring中,模板方法模式被广泛应用,例如JdbcTemplate、RedisTemplate和RestTemplate等都使用了模板方法模式。

例如,下面是一个简单的例子,它演示了如何在Spring中使用模板方法模式来定义一个抽象类及其子类:

public abstract class MyAbstractClass {
    public final void templateMethod() {
        // 调用抽象方法
        abstractMethod();
        // 调用具体方法
        concreteMethod();
    }

    protected abstract void abstractMethod();

    private void concreteMethod() {
        // 具体实现
    }
}

public class MyClass extends MyAbstractClass {
    @Override
    protected void abstractMethod() {
        // 实现抽象方法
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在上面的例子中,我们定义了一个抽象类MyAbstractClass,它包含一个模板方法templateMethod。这个方法调用了一个抽象方法abstractMethod和一个具体方法concreteMethod。我们还定义了一个子类MyClass,它继承自MyAbstractClass并重写了抽象方法abstractMethod。

Kafka
Linux基本指令

← Kafka Linux基本指令→

最近更新
01
实习技术
08-24
02
sql
07-28
03
git命令
07-26
更多文章>
Theme by Vdoing | Copyright © 2019-2023 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式