【设计模式】策略模式

477 阅读1分钟

模式介绍

一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

示例

if (type == "A") {
    // A逻辑
} else if (type == "B") {
    // B逻辑
} else { 
    // 其他逻辑
}

解决有多个if...else等条件分支的情况

定义策略

public interface BaseStrategy {

    public final static String KEY_CONCAT = "_";

    String getStrategyKey();
}
public interface IStrategy  extends BaseStrategy {

    public final static String ESTATE_STRATEGY_KEY_PREFIX = IStrategy.class.getSimpleName() + KEY_CONCAT;

    void deal1();

    void deal2();
}

添加策略

A

import com.design.pattern.strategy.IStrategy;
import com.design.pattern.strategy.TypeEnum;
import org.springframework.stereotype.Service;

@Service
public class AStrategyImpl implements IStrategy {

    @Override
    public String getStrategyKey() {
        return ESTATE_STRATEGY_KEY_PREFIX + TypeEnum.A.getCode();
    }

    @Override
    public void deal1() {
        System.out.println("处理A逻辑的1事件");
    }

    @Override
    public void deal2() {
        System.out.println("处理A逻辑的1事件");
    }
}

B

import com.design.pattern.strategy.IStrategy;
import com.design.pattern.strategy.TypeEnum;
import org.springframework.stereotype.Service;

@Service
public class BStrategyImpl implements IStrategy {

    @Override
    public String getStrategyKey() {
        return ESTATE_STRATEGY_KEY_PREFIX + TypeEnum.B.getCode();
    }

    @Override
    public void deal1() {
        System.out.println("处理B逻辑的1事件");
    }

    @Override
    public void deal2() {
        System.out.println("处理B逻辑的2事件");
    }
}

其他

import com.design.pattern.strategy.IStrategy;
import com.design.pattern.strategy.TypeEnum;
import org.springframework.stereotype.Service;

@Service
public class OtherStrategyImpl implements IStrategy {

    @Override
    public String getStrategyKey() {
        return ESTATE_STRATEGY_KEY_PREFIX + TypeEnum.Other.getCode();
    }

    @Override
    public void deal1() {
        System.out.println("处理其他逻辑的1事件");
    }

    @Override
    public void deal2() {
        System.out.println("处理其他逻辑的2事件");
    }
}

将策略加载至工厂

使用ApplicationContextAware接口,把所有的策略,初始化到iStrategyMap里面。然后对外提供getStrategy方法。

@Component
public class TypeStrategyFactory implements ApplicationContextAware {

    private Map<String, IStrategy> iStrategyMap = new ConcurrentHashMap<>();

    public <T extends IStrategy> T getStrategy(String strategyKey) throws Exception {
        IStrategy strategy = iStrategyMap.get(IStrategy.ESTATE_STRATEGY_KEY_PREFIX + strategyKey);
        if (strategy == null) {
            throw new Exception("TypeStrategyFactory.getStrategy is error, strategyKey is " + strategyKey);
        }
        return (T) strategy;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, IStrategy> map = applicationContext.getBeansOfType(IStrategy.class);
        map.forEach((key, value) -> iStrategyMap.put(value.getStrategyKey(), value));
    }
}

优缺点

优点

  1. 避免使用多重条件判断
  2. 扩展性良好。
  3. 算法可以自由切换

缺点

  1. 策略类会增多。
  2. 所有策略类都需要对外暴露。