为什么要设计使用策略模式
- 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。
- 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
- 实现方式的解耦,便于扩展。
以交易实现为例
交易策略的定义
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_
}
交易方式策略的实现
- 线下交易
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线下交易");
}
}
- 线上交易
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结束");
}
}