设计模式-策略模式

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

    }


}
相关推荐
她说..5 小时前
策略模式+工厂模式实现审批流(面试问答版)
java·后端·spring·面试·springboot·策略模式·javaee
YigAin7 小时前
Unity23种设计模式之 命令模式
设计模式·命令模式
twj_one8 小时前
java中23种设计模式
java·开发语言·设计模式
香芋Yu8 小时前
【深度学习教程——01_深度基石(Foundation)】05_数据太多怎么吃?Mini-batch训练的设计模式
深度学习·设计模式·batch
进击的小头12 小时前
设计模式组合应用:传感器数据采集与处理系统
c语言·设计模式
茶本无香13 小时前
设计模式之十一—桥接模式:解耦抽象与实现的艺术
设计模式·桥接模式
短剑重铸之日13 小时前
《设计模式》第四篇:观察者模式
java·后端·观察者模式·设计模式
七夜zippoe15 小时前
API网关设计模式实战 Spring Cloud Gateway路由过滤限流深度解析
java·设计模式·gateway·路由·api网关
yangpipi-1 天前
2. 设计模式之结构型模式
设计模式
进击的小头1 天前
设计模式组合应用:嵌入式通信协议栈
c语言·设计模式·策略模式