设计模式-策略模式

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();

    }


}
相关推荐
怕浪猫13 小时前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane199416 小时前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
Zane19942 天前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..2 天前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1502 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)3 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki3 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅664 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa4 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio
sarasuki4 天前
如何让 Agent 获取更多的能力?插件 / 技能系统
人工智能·设计模式·agent