设计模式-策略模式(三)

87 阅读1分钟

为什么要设计使用策略模式

  1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if...else 语句、switch...case 语句。
  2. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
  3. 实现方式的解耦,便于扩展。

以交易实现为例

交易策略的定义

package com.enterprise.account.service.model.strategy;

/**
 * @version 1.0
 * @date 2021/8/20 5:33 下午
 * @desc 交易策略
 * @since 1.0
 */
public interface TransactionStrategy<T> {

    T transactionEnum();

    void transaction();
}

package com.enterprise.account.service.model.strategy;

import lombok.NoArgsConstructor;

/**
 * @version 1.0
 * @date 2021/8/23 4:02 下午
 * @desc 交易方式
 * @since 1.0
 */
@NoArgsConstructor
public enum TransactionEnum {
    ONLINE_,
    OUTLINE_
}

交易方式策略的实现

  1. 线下交易
package com.enterprise.account.service.model.strategy.transaction;

import com.enterprise.account.service.model.strategy.TransactionEnum;
import com.enterprise.account.service.model.strategy.TransactionStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @version 1.0
 * @date 2021/8/23 4:03 下午
 * @desc 线下交易实现
 * @since 1.0
 */
@Slf4j
@Service
public class OutlineImpl implements TransactionStrategy<TransactionEnum> {

    @Override
    public TransactionEnum transactionEnum() {
        return TransactionEnum.OUTLINE_;
    }

    @Override
    public void transaction() {
        log.info("\n线下交易");
    }
}
  1. 线上交易
package com.enterprise.account.service.model.strategy.transaction;

import com.enterprise.account.service.model.strategy.TransactionEnum;
import com.enterprise.account.service.model.strategy.TransactionStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @since 1.0
 * 线上交易实现
 */
@Slf4j
@Service
public class OnlineImpl implements TransactionStrategy<TransactionEnum> {

    @Override
    public TransactionEnum transactionEnum() {
        return TransactionEnum.ONLINE_;
    }

    @Override
    public void transaction() {
        log.info("\n线上交易");
    }
}

交易实现放到容器管理,使用时从容器中获取

package com.enterprise.account.service.model.strategy;

import com.google.common.collect.Maps;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class InitializingTransactionBeans implements ApplicationContextAware {
    public static final Map<TransactionEnum, TransactionStrategy> transactionBeanMap = Maps.newHashMap();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, TransactionStrategy> beansOfType = applicationContext.getBeansOfType(TransactionStrategy.class);
        beansOfType.forEach((k, v) -> {
            transactionBeanMap.put((TransactionEnum) v.transactionEnum(), v);
        });
    }
}

使用

package com.enterprise.account.service.model.strategy;

import org.springframework.stereotype.Service;

@Service
public class TransactionStrategyService {

    public void transaction(TransactionEnum transactionEnum) {
        TransactionStrategy transactionStrategy = InitializingTransactionBeans.transactionBeanMap.get(transactionEnum);
        transactionStrategy.transaction();
    }

}

test

package com.enterprise.account.service.model.strategy;

import com.enterprise.account.AccountServiceApp;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AccountServiceApp.class)
public class TransactionStrategyImplTest {

    @Autowired
    private TransactionStrategyService transactionStrategyService;

    @Test
    public void transaction() {
        transactionStrategyService.transaction(TransactionEnum.ONLINE_);
        transactionStrategyService.transaction(TransactionEnum.OUTLINE_);

        log.info("\n结束");
    }
}