设计模式-策略模式

221. 策略模式是一个非常简单且非常实用的一种设计模式

策略模式的核心是选择,动态切换 ,通过条件拿到相应的策略 () , 本质上是对行为的抽象

2. 示例演示 - 定义不同的玩家客服和选择逻辑

2.1 起一个有意义的接口名字时更能反映出接口名字相应的内容

java 复制代码
package org.example.service;

// 客服的通用接口

public interface CustomerService  {
    String findCustomer();
}

2.2 定义四种不同的客服的实现,然后都交给Spring容器管理

java 复制代码
import org.example.controller.SupportUserType;
import org.springframework.stereotype.Service;

@Service
@SupportUserType(CustomerType.BIG)
public class BigCustomerService implements CustomerService {


    @Override
    public String findCustomer() {
        return "BigCustomerService";
    }

}

import org.example.controller.SupportUserType;
import org.springframework.stereotype.Service;

@Service
@SupportUserType(CustomerType.SUPER)
public class SuperRCustomerService implements CustomerService {

    @Override
    public String findCustomer() {
        return "SuperRCustomerService";
    }
}




import org.springframework.stereotype.Component;

@Service
public class DefaultCustomService implements CustomerService{


    @Override
    public String findCustomer() {
        return "没有找到客服";
    }
}



import org.example.controller.SupportUserType;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

@Service
//@Order(4)
@SupportUserType(CustomerType.NORMAL)
public class NormalCustomerService implements CustomerService {


    @Override
    public String findCustomer() {
        return "NormalCustomerService";
    }
}


import org.springframework.stereotype.Component;

@Component
public class DefaultCustomService implements CustomerService{


    @Override
    public String findCustomer() {
        return "没有找到客服";
    }
}

2.3 定义枚举类 每种不同的客服对应不同的金额,使用函数式接口判断不同的类型。不同的金额对应的类型不同。

java 复制代码
import java.util.function.IntPredicate;

// 定义 客服类型的一个枚举 字符串
public enum CustomerType {

    NORMAL(e-> e>0 && e<1000),

    BIG(e-> e>=1000 && e<2000),

    SMAIL(e-> e>=2000 && e<3000),

    SUPER(e-> e>=3000 && e<4000);

    private final IntPredicate support;

    CustomerType( IntPredicate support ) {
         this.support = support;
    }

    public static CustomerType typeOf( int reChange ) {
        for (CustomerType value : values()) {
            if(value.support.test( reChange )) {
                return value;
            }
        }
        return null;
    }
}

2.4 创建枚举,对每种客服的实现类进行标识。

java 复制代码
import org.example.service.CustomerType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SupportUserType {
    CustomerType value();
}

2.2 代码有具体实现,亦如下

java 复制代码
import org.example.controller.SupportUserType;
import org.springframework.stereotype.Service;

@Service
@SupportUserType(CustomerType.BIG)
public class BigCustomerService implements CustomerService {


    @Override
    public String findCustomer() {
        return "BigCustomerService";
    }

}

2.5 通过反射的方式都文件进行解析和加载,在analystType方法中加上@Resource注解,在Spring容器初始化阶段 ,将解析到的类型和类型对应的实现放入到一个map中,当用户请求相应的controller接口时,就会将金额解析成为对应的枚举,并通过枚举拿到对应的实例对象,通过对象拿到相应的方法,当然当用户输入的金额是非法无法匹配时则直接会返回一个默认的对象。

java 复制代码
import jakarta.annotation.Resource;
import org.example.service.CustomerService;
import org.example.service.CustomerType;
import org.example.service.DefaultCustomService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/customer")
public class CustomerController {

    private Map<CustomerType,CustomerService> map;

    // 手动注入
    @Resource
    private DefaultCustomService defaultCustomService;

    @GetMapping("/customer/{reChange}")
    public String controller(@PathVariable(value = "reChange") Integer reChange) {
        CustomerType customerType = CustomerType.typeOf(reChange);
        CustomerService customerService = map.getOrDefault(customerType , defaultCustomService);
        return customerService.findCustomer();
    }

   // Spring 的 Bean 容器注入时就会执行该方法
    @Resource
    public void analystType(List<CustomerService>  customerServices ) {
        map = customerServices.stream()
                .filter(customerService -> customerService.getClass().isAnnotationPresent(SupportUserType.class))
                .collect(Collectors.toMap(this::findCustomerType, Function.identity()));
       // 策略和处理器的数量的一致性
        if (this.map.size() != CustomerType.values().length ) {
            throw new IllegalStateException("Customer type count mismatch 由用户类型没有对应的策略");
        }
    }


    private CustomerType findCustomerType(CustomerService customerService) {
        SupportUserType annotation = customerService.getClass().getAnnotation(SupportUserType.class);
        return annotation.value();

    }


}
相关推荐
xiaolyuh12321 小时前
Spring 框架 核心架构设计 深度详解
spring·设计模式·spring 设计模式
GISer_Jing1 天前
智能体工具使用、规划模式
人工智能·设计模式·prompt·aigc
GISer_Jing1 天前
AI Agent:学习与适应、模型上下文协议
人工智能·学习·设计模式·aigc
小马爱打代码1 天前
MyBatis设计模式:构建者、工厂、代理模式
设计模式·mybatis·代理模式
月明长歌1 天前
Javasynchronized 原理拆解:锁升级链路 + JVM 优化 + CAS 与 ABA 问题(完整整合版)
java·开发语言·jvm·安全·设计模式
会员果汁1 天前
12.设计模式-状态模式
设计模式·状态模式
且去填词1 天前
DeepSeek :基于 AST 与 AI 的遗留系统“手术刀”式治理方案
人工智能·自动化·llm·ast·agent·策略模式·deepseek
Yu_Lijing1 天前
基于C++的《Head First设计模式》笔记——抽象工厂模式
c++·笔记·设计模式
会员果汁2 天前
13.设计模式-适配器模式
设计模式·适配器模式
GISer_Jing2 天前
AI:多智能体协作与记忆管理
人工智能·设计模式·aigc