设计模式

设计模式

前言

设计模式是一种通用的思维方式,可以在各个行业和领域中应用,帮助设计师和工程师解决复杂的设计和工程问题,提高系统的质量和效率。

在软件开发过程中,我们要减少重复代码,对修改关闭,对扩展开放,但是切勿提前过度设计。设计模式不是银弹,过度使用设计模式反而会使代码变得复杂和难以理解。

参考基本原则

  1. 单一职责原则(Single Responsibility Principle,SRP):一个类应该只有一个引起变化的原因。换句话说,一个类应该只有一个责任。
  2. 开闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。即对于已经实现的功能模块,应该在不修改其源代码的情况下进行扩展。
  3. 里氏替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换其基类型而不影响程序的正确性。换句话说,任何基类可以出现的地方,子类一定可以出现。
  4. 依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。
  5. 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖于它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口数量上。
  6. 迪米特法则(Law of Demeter,LoD):一个对象应该对其他对象有尽可能少的了解,不和陌生类发生关系,只和朋友类发生关系。

面向对象设计原则

  • 组合优于及继承
  • 最小化接口暴露
  • 消除代码重复:
  • 工厂模式+模板方法模式
    策略模式
    注解+反射
    重复出现三次,要抽象了
  • 把函数写短,越短越好。
  • 分离关注点,发现的关注点越多越好,粒度越小越好。
  • 识别对象的不同角色,设计小接口
  • 基于行为进行封装,不要暴露实现细节,最小化接口暴露。
  • 依赖于构建出来的抽象,而不是具体类。面向对象设计和实现:
    1.划分职责识别类
    2.定义属性和方法
    3.定义类之间的交互关系
    4.组装类并提供执行入口

工厂+策略模式

首先定义一个枚举类 ExecutorType

public enum ExecutorType {
    TYPE1,
    TYPE2,
}

定义Executor接口和实现

public interface Executor {
    void execute();
    ExecutorType getType(); // 修改返回值为枚举类型
}

@Component
public class ExecutorImpl1 implements Executor {
    @Override
    public void execute() {
        System.out.println("执行实现类1的操作");
    }

    @Override
    public ExecutorType getType() {
        return ExecutorType.TYPE1;
    }
}

@Component
public class ExecutorImpl2 implements Executor {
    @Override
    public void execute() {
        System.out.println("执行实现类2的操作");
    }

    @Override
    public ExecutorType getType() {
        return ExecutorType.TYPE2;
    }
}

初始化类ExecutorInitializer,使用map构造实现类工厂

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class ExecutorInitializer implements BeanPostProcessor {

    private final Map<ExecutorType, Executor> executorMap = new HashMap<>();

    @Autowired
    private void addExecutor(Executor executor) {
        executorMap.put(executor.getType(), executor);
    }

    public Executor getExecutor(ExecutorType type) {
        return executorMap.get(type);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Executor) {
            addExecutor((Executor) bean);
        }
        return bean;
    }
}

在服务类中,我们使用这个初始化类来获取实现类的实例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    @Autowired
    private ExecutorInitializer executorInitializer;

    public void executeByType(ExecutorType type) {
        Executor executor = executorInitializer.getExecutor(type);
        if (executor != null) {
            executor.execute();
        } else {
            System.out.println("未找到对应类型的执行器");
        }
    }
}

状态机模式

spring-statemachine使用

  • 引入maven依赖
<!--状态机-->
        <dependency>
            <groupId>org.springframework.statemachine</groupId>
            <artifactId>spring-statemachine-starter</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
  • 定义状态机的状态与事件(OrderState,OrderEvents)

OrderState:

public enum OrderState {
    UNPAID,                 // 待支付
    WAITING_FOR_RECEIVE,    // 待收货
    DONE                    // 结束
}

OrderEvents:

public enum OrderEvents {
    PAY,        // 支付
    RECEIVE     // 收货
}
  • 将状态与事件进行绑定(StateMachineConfig)
@Configuration
@EnableStateMachine(name = "StateMachineConfig")
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvents> {

    private Logger logger = LoggerFactory.getLogger(getClass());
    //定义初始状态
    @Override
    public void configure(StateMachineStateConfigurer<OrderState, OrderEvents> states)
            throws Exception {
        states
            .withStates()
                .initial(OrderState.UNPAID)
                .states(EnumSet.allOf(OrderState.class));
    }
    //状态转换过程 触发什么事件就转换为什么状态
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvents> transitions)
            throws Exception {
        transitions
            .withExternal()
                .source(OrderState.UNPAID).target(OrderState.WAITING_FOR_RECEIVE)
                .event(OrderEvents.PAY)
                .and()
            .withExternal()
                .source(OrderState.WAITING_FOR_RECEIVE).target(OrderState.DONE)
                .event(OrderEvents.RECEIVE);
    }
}
  • 将事件监听触发与配置类进行配置(EventListener)
@Component
@WithStateMachine(name = "StateMachineConfig")
public class EventListener {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @OnTransition(target = "UNPAID")
    public boolean create(Message<Order> order) {     // 创建订单逻辑
        logger.info("订单创建,待支付");
        return true;
    }

    @OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE")
    public boolean pay(Message<Order> order) {
        // 支付逻辑 从redis根据order 来进行处理
        logger.info("用户完成支付,待收货");
        return true;
    }

    @OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE")
    public boolean receive(Message<Order> order) {     //从redis中根据传入的order 来查询当前订单 并业务处理
        logger.info("用户已收货,订单完成");
        return true;
    }

}
  • 启动测试
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
    public DemoApplication(StateMachine<OrderState, OrderEvents> stateMachine) {
        this.stateMachine = stateMachine;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    private final StateMachine<OrderState, OrderEvents> stateMachine;

    @Override
    public void run(String... args) throws Exception {
        Order order=new Order("测试",0);
        // 使用 MessageBuilder 创建消息并设置负载和头信息
        Message message = MessageBuilder
                .withPayload(OrderEvents.PAY)
                .setHeader("order", order)
                .build();
        // 发送消息给状态机
        stateMachine.start();
        stateMachine.sendEvent(message);
    }
}

模板方法

抽象模板类AbstractTemplate定义算法骨架,类型为final类型,需要子类实现的定义为protected abstract 类型。

// 抽象模板类
abstract class AbstractTemplate {

    // 模板方法,定义了算法的骨架
    public final void templateMethod() {
        step1();
        step2();
        step3();
    }

    // 基本方法,由子类实现
    protected abstract void step1();

    // 基本方法,由子类实现
    protected abstract void step2();

    // 基本方法,由子类实现
    protected abstract void step3();
}

// 具体子类1
class ConcreteClass1 extends AbstractTemplate {

    @Override
    protected void step1() {
        System.out.println("ConcreteClass1: Step 1");
    }

    @Override
    protected void step2() {
        System.out.println("ConcreteClass1: Step 2");
    }

    @Override
    protected void step3() {
        System.out.println("ConcreteClass1: Step 3");
    }
}

// 具体子类2
class ConcreteClass2 extends AbstractTemplate {

    @Override
    protected void step1() {
        System.out.println("ConcreteClass2: Step 1");
    }

    @Override
    protected void step2() {
        System.out.println("ConcreteClass2: Step 2");
    }

    @Override
    protected void step3() {
        System.out.println("ConcreteClass2: Step 3");
    }
}

spring boot使用示例

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private ConcreteClass1 concreteClass1;

    @Autowired
    private ConcreteClass2 concreteClass2;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        concreteClass1.templateMethod();
        concreteClass2.templateMethod();
    }

posted @ 2024-04-23 15:04  曹化金  阅读(9)  评论(0编辑  收藏  举报