策略模式

策略模式在源代码中通常以StrategyPolicyHandler结尾,其中大多数以后2者为多,比如在JUC中,创建ThreadPoolExecutor对象需要一个RejectedExecutionHandler对象,该接口就是典型的策略模式接口。他有几个子类,比如DiscardOldestPolicyAbortPolicy等。

应用场景:JUC

  1. 创建ThreadPoolExecutor对象需要一个RejectedExecutionHandler对象,改接口就是一种策略模式,拥有不同的实现,每个实现都代表着一种不同的拒绝策略。

策略工厂消除ifelse

Spring策略工厂方式一

相关设计模式:

  1. 策略

  2. 工厂

  3. 享元

  4. spring Bean生命周期方法

  5. 模板方法

消息类型枚举,是判别策略的维度:

public enum MessageType {

    TYPE_A, 
    TYPE_B, 
    TYPE_C,
    ;
}

策略接口 MqSenderStrategy,实现Spring生命周期方法,用于在初始化后注册策略实现到Factory中:

public interface MqSenderStrategy extends InitializingBean{

    void send(String message);

}

抽象策略,可以引入模板方法模式,实现公共的业务逻辑:

public abstract class AbstractMqSenderStrategy implements MqSenderStrategy {

    protected abstract MessageType getMessageType();

    // 使用生命周期方法注册到工厂类中
    // 也可以使用@PostConstuct
    @Override
    public void afterPropertiesSet() throws Exception {
        MqSenderStrategyFactory.registrySender(getMessageType(), this);
    }
        
    /**
     * 发送模板代码封装
     */
    @Override
    public void send(String message) {
        // Connection c = new Connection(); 创建连接
        // c.connect()
        doSend(message);
        // c.disconnect(); 断开连接
    }

    protected abstract void doSend(String message);
        
}

策略实现:

@Component
public class ASenderStrategy extends AbstractMqSenderStrategy {

    @Override
    protected MessageType getMessageType() {
        return MessageType.TYPE_A;
    }
        
    @Override
    public void doSend(String message) {
    }

}

工厂类:

public class MqSenderStrategyFactory {
        
    private static final ConcurrentHashMap<MessageType, MqSenderStrategy> SENDER_MAP;
        
    static {
        SENDER_MAP = new ConcurrentHashMap<>(MessageType.values().length);
    }
        
    public static void registrySender(MessageType messageType, MqSenderStrategy     mqSenderStrategy) {
        if (messageType == null) {
            throw new RuntimeException("注册Sender到Factory失败,消息类型不可为null");
        }
        
        if (SENDER_MAP.get(messageType) != null) {
            throw new RuntimeException("相同类型的消息处理策略只能注册到Factory一次");
        }
        
        SENDER_MAP.put(messageType, mqSenderStrategy);
    }
    
    public static MqSenderStrategy getSender(MessageType messageType) {
        return SENDER_MAP.get(messageType);
    }
}

Spring策略工厂方式二

与方式一相比:

  1. Factory类加入Spring IoC

  2. 策略类使用Autowrid机制自动加入到Factory中,而不是通过生命周期钩子主动注入,策略类更简洁,与Factory耦合更小

  3. 使用List存储策略实现类,然后可以通过@Order注解控制策略实现类的优先级(当策略选择条件复杂时,有可能多个策略同时满足,这个可以通过优先级处理)

策略接口不需要集成生命周期函数,需要暴露getMessageType方法供工厂类使用 :

public interface MqSenderStrategy {

    MessageType getMessageType();

    void send(String message);

}

策略实现:

@Component
@Order(1)
@Lazy
public class ASenderStrategy extends AbstractMqSenderStrategy {

    @Override
    protected MessageType getMessageType() {
        return MessageType.TYPE_A;
    }
        
    @Override
    public void doSend(String message) {
    }

}

策略工厂加入IoC,并且注入所有实现进入:

public class MqSenderStrategyFactory {

    @Autowried
    private List<MqSenderStrategy> sendList;
        
    private static final ConcurrentHashMap<MessageType, MqSenderStrategy> SENDER_MAP; 
        
    static {
        SENDER_MAP = new ConcurrentHashMap<>(MessageType.values().length);
    }
        
    // 工厂对象创建完毕,初始化策略工厂
    @PostConstruct
    public void registrStrategy() {
        sendList.forEach(e - > SENDER_MAP.put(e.getMessageType()));
    }
    
    public static MqSenderStrategy getSender(MessageType messageType) {
        return SENDER_MAP.get(messageType);
    }
}

最后更新于