设计模式
设计模式
前言
设计模式是一种通用的思维方式,可以在各个行业和领域中应用,帮助设计师和工程师解决复杂的设计和工程问题,提高系统的质量和效率。
在软件开发过程中,我们要减少重复代码,对修改关闭,对扩展开放,但是切勿提前过度设计。设计模式不是银弹,过度使用设计模式反而会使代码变得复杂和难以理解。
参考基本原则
- 单一职责原则(Single Responsibility Principle,SRP):一个类应该只有一个引起变化的原因。换句话说,一个类应该只有一个责任。
- 开闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。即对于已经实现的功能模块,应该在不修改其源代码的情况下进行扩展。
- 里氏替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换其基类型而不影响程序的正确性。换句话说,任何基类可以出现的地方,子类一定可以出现。
- 依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。
- 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖于它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口数量上。
- 迪米特法则(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();
}