策略模式实例

需求描述

购买手机分为三个手机厂商:华为手机、小米手机、OPPO手机,根据每个手机厂商编码查看对应厂商旗舰手机。

代码实现

初始化容器配置

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 初始化配置容器
 * 
 * @author leizi
 * @date 2024/03/17
 */
@Component
@Slf4j
public class AppContext implements ApplicationContextAware {

    private static ApplicationContext appContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (null == appContext) {
            if (null != applicationContext) {
                AppContext.appContext = applicationContext;
            }
            log.info("Spring init successfully");
        }

    }

    public static ApplicationContext getContext() {
        if (appContext == null) {
            throw new IllegalStateException("applicationContext inject failure,please restart the service");
        }
        return appContext;
    }
}

厂商类型枚举

/**
 * 手机厂商枚举
 *
 * @author leizi
 * @date 2024/03/17
 */
public enum SourceTypeEnum {

    HUAWEI(1, "华为厂商"),
    XIAOMI(2, "小米厂商"),
    OPPO(3, "OPPO厂商");

    private Integer type;

    private String memo;

    SourceTypeEnum(Integer type, String memo) {
        this.type = type;
        this.memo = memo;
    }

    public Integer getType() {
        return type;
    }

    public String getMemo() {
        return memo;
    }

    /**
     * 根据类型获取实例
     *
     * @param type
     * @return
     */
    public static SourceTypeEnum getInstance(Integer type) {
        if (null == type) {
            return null;
        }
        for (SourceTypeEnum typeEnum : SourceTypeEnum.values()) {
            if (typeEnum.type.equals(type)) {
                return typeEnum;
            }
        }
        return null;
    }
}

策略来源注解

import com.example.demo.enums.SourceTypeEnum;
import org.springframework.stereotype.Component;

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

/**
 * 厂商来源注解
 *
 * @author leizi
 * @date 2024/03/17
 */
@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface SourceType {

    SourceTypeEnum value();

}

厂商来源工厂配置

/**
 * @author leizi
 * @date 2024/03/18
 */
public interface InitProcess {
    /**
     * 初始化工厂
     */
    void init();
}
import cn.hutool.core.map.MapUtil;
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author leizi
 * @date 2024/03/17
 */
@Component
@Slf4j
public class FactoryHandlerStrategy implements InitProcess {

    private static ConcurrentHashMap<SourceTypeEnum, PhoneManufacturerService> phoneManufacturerMap = new ConcurrentHashMap<>();

    @Override
    public void init() {
        initPhoneManufacturer();
    }

    /**
     * 初始化phoneManufacturerMap
     */
    private void initPhoneManufacturer() {
        // 加载PhoneManufacturerService 厂商处理实现类
        Map<String, PhoneManufacturerService> mapPhoneManufacturer = AppContext.getContext().getBeansOfType(PhoneManufacturerService.class);
        mapPhoneManufacturer.entrySet().stream().forEach(entry -> {
            Class<? extends Object> clazz = entry.getValue().getClass();
            SourceType annotation = clazz.getAnnotation(SourceType.class);
            /*if (null == annotation) {
                // 这里为处理方法使用@Async,SourceType类型获取失效问题
                Map<String, Object> map = JSON.parseObject(JSON.toJSONString(entry.getValue()));
                Object decoratedClass = map.get("decoratedClass");
                try {
                    clazz = Class.forName(decoratedClass.toString());
                    annotation = clazz.getAnnotation(SourceType.class);
                } catch (Exception e) {
                    log.error("class forName error:{}", e);
                }
            }*/
            if (null == annotation) {
                return;
            }
            SourceTypeEnum sourceType = annotation.value();
            if (null != sourceType) {
                PhoneManufacturerService phoneManufacturerService = phoneManufacturerMap.get(sourceType);
                if (null != phoneManufacturerService) {
                    phoneManufacturerMap.remove(sourceType);
                }
                phoneManufacturerMap.put(sourceType, entry.getValue());
            }
        });
    }

    /**
     * 根据厂商来源获取实现类
     *
     * @param sourceType
     * @return
     */
    public PhoneManufacturerService getPhoneManufacturer(SourceTypeEnum sourceType) {
        if (MapUtil.isEmpty(phoneManufacturerMap)) {
            initPhoneManufacturer();
        }
        return phoneManufacturerMap.get(sourceType);
    }


}

初始化来源工厂配置

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 初始配置
 *
 * @author leizi
 * @date 2024/03/18
 */
@Component
public class InitContext implements ApplicationRunner {

    private final FactoryHandlerStrategy factoryHandlerStrategy;

    public InitContext(FactoryHandlerStrategy factoryHandlerStrategy) {
        this.factoryHandlerStrategy = factoryHandlerStrategy;
    }

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        /*
         * 容器启动完成把实现InitProcess实现类都执行init初始化操作,根据实际需要实现
         * */
//        Map<String, InitProcess> processMap = AppContext.getContext().getBeansOfType(InitProcess.class);
        factoryHandlerStrategy.init();
    }
}

业务代码

/**
 * @author leizi
 * @date 2024/03/17
 */
public interface PhoneManufacturerService {

    /**
     * 根据厂商类型查看手机
     *
     * @param type 厂商类型
     * @return
     */
    String getPhone(Integer type);

    /**
     * 购买指定厂商手机
     *
     * @param type 厂商类型
     * @return
     */
    String buyPhone(Integer type);

}
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;

/**
 * OPPO厂商手机
 *
 * @author leizi
 * @date 2024/03/17
 */
@SourceType(SourceTypeEnum.OPPO)
public class OppoManufacturerServiceImpl implements PhoneManufacturerService {
    @Override
    public String getPhone(Integer type) {
        return "一台OPPOFindX500旗舰手机";
    }

    @Override
    public String buyPhone(Integer type) {
        return "购买了OPPOFindX500旗舰手机";
    }
}
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;

/**
 * 小米厂商手机
 *
 * @author leizi
 * @date 2024/03/17
 */
@SourceType(SourceTypeEnum.XIAOMI)
public class XiaomiManufacturerServiceImpl implements PhoneManufacturerService {
    @Override
    public String getPhone(Integer type) {
        return "一台小米100pro旗舰手机";
    }

    @Override
    public String buyPhone(Integer type) {
        return "购买了小米100pro旗舰手机";
    }
}
import com.example.demo.annotation.SourceType;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;

/**
 * 华为厂商手机
 *
 * @author leizi
 * @date 2024/03/17
 */
@SourceType(SourceTypeEnum.HUAWEI)
public class HuaweiManufacturerServiceImpl implements PhoneManufacturerService {

    @Override
    public String getPhone(Integer type) {
        return "一台华为Mete100旗舰手机";
    }

    @Override
    public String buyPhone(Integer type) {
        return "购买了华为Mete100旗舰手机";
    }
}
import com.example.demo.config.FactoryHandlerStrategy;
import com.example.demo.enums.SourceTypeEnum;
import com.example.demo.service.PhoneManufacturerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author leizi
 * @date 2024/03/17
 */
@RestController
@RequestMapping("/phone")
public class PhoneController {

    private final FactoryHandlerStrategy factoryHandlerStrategy;

    public PhoneController(FactoryHandlerStrategy factoryHandlerStrategy) {
        this.factoryHandlerStrategy = factoryHandlerStrategy;
    }


    @GetMapping("/get")
    public String getPhone(@RequestParam Integer type) {

        PhoneManufacturerService manufacturerService = factoryHandlerStrategy.getPhoneManufacturer(SourceTypeEnum.getInstance(type));
        if (null != manufacturerService) {
            return manufacturerService.getPhone(type);
        }
        return "获取失败了";
    }

}
posted @ 2024-03-18 22:49  Lz_蚂蚱  阅读(10)  评论(0编辑  收藏  举报