设计模式-策略模式

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

    }


}
相关推荐
猿月亮6 小时前
Java设计模式之-组合模式
java·设计模式·组合模式
贱贱的剑7 小时前
7. 命令模式
设计模式·命令模式
夜宵饽饽9 小时前
氛围编码(Vice Coding)的工具选择方式
设计模式·敏捷开发
大飞pkz9 小时前
【设计模式&C#】享元模式(用于解决多次创建对象而导致的性能问题)
开发语言·设计模式·c#·享元模式
Code季风10 小时前
深入理解 Spring 设计模式:从实现原理到思想精髓
java·spring·设计模式
DKPT12 小时前
Java设计模式之行为型模式(备忘录模式)应用场景分析
java·笔记·学习·设计模式·备忘录模式
万粉变现经纪人13 小时前
如何解决pip安装报错ModuleNotFoundError: No module named ‘pillow’问题
python·pycharm·beautifulsoup·pandas·pillow·pip·策略模式
hqxstudying13 小时前
Java行为型模式---访问者模式
java·开发语言·windows·设计模式·访问者模式
归云鹤17 小时前
设计模式五:桥模式(Bridge Pattern)
算法·设计模式·桥接模式