今天起,在我的博客开一个专题,专门写一些个人对于设计模式的理解,众所周知,常用的设计模式有大概23种,那让我们一个个来看看日常工作中如何更好的使用他们吧~
首先要讲的是工厂模式,直接用例子跟大家讲清楚这些事情,我们先定义一个奖励发送的接口类:
public interface RewardService {
/**
* 发放奖励
* @param userId 用户id
* @param rewordId 奖励品id
* @param bizId 业务唯一code
* @param extMap 扩展字段
*/
void giveReword(Long userId, Long rewordId, String bizId, Map<String,String> extMap);
}
紧接着有三个不同的实现类(Strategy为自定义注解,后续会使用到):
@Slf4j
@Service
@Strategy(rewardType = Constants.REWARD.ECARD_REWORD)
public class ECardRewardSpringService implements RewardSpringService {
@Override
public void giveReword(Long userId, Long rewordId, String bizId, Map<String, String> extMap) {
//模仿发送奖励代码
log.info("发送卡片奖励给用户:{},奖励为:{},业务code为:{}",userId,rewordId,bizId);
}
}
@Slf4j
@Slf4j
@Service
@Strategy(rewardType = Constants.REWARD.MATERIAL_REWOD)
public class MaterialRewardSpringService implements RewardSpringService {
@Override
public void giveReword(Long userId, Long rewordId, String bizId, Map<String, String> extMap) {
//模仿发送奖励代码
log.info("发送实物奖励给用户:{},奖励为:{},业务code为:{}",userId,rewordId,bizId);
}
}
@Slf4j
@Service
@Strategy(rewardType = Constants.REWARD.VIRTUAL_REWORD)
public class VirtualRewardSpringService implements RewardSpringService {
@Override
public void giveReword(Long userId, Long rewordId, String bizId, Map<String, String> extMap) {
//模仿发送奖励代码
log.info("发送虚拟奖励给用户:{},奖励为:{},业务code为:{}",userId,rewordId,bizId);
}
}
那我们想要调用不同的奖励发放逻辑,通常的代码都是这样写的
public class SimpleFactoryTests {
@Test
public void testGetRewordByUsual(Integer rewardType){
if(rewardType == 1){
RewardService rewardService = new ECardRewardService();
rewardService.giveReword(111L,222L,"reword1",new HashMap<>());
} else if(rewardType == 2){
RewardService rewardService = new MaterialRewardService();
rewardService.giveReword(222L,333L,"reword2",new HashMap<>());
} else if(rewardType == 3){
RewardService rewardService = new VirtualRewardService();
rewardService.giveReword(444L,555L,"reword3",new HashMap<>());
}
}
}
当后面新增新的的奖励类型的时候,我们就会来改这段代码,新增if else判断,久而久之,这段代码就会越来越长,最终成为s***山代码了,那采用工厂模式的话,就可以轻松将去除掉这边的if else语句了,那我们从浅入深,看看工厂模式如何正确运用的吧~
话不多说,直接上代码:
public class SimpleFactory {
/**
* 通过奖励类型返回奖励服务类
* @param rewordType 奖励类型
* @return
*/
public RewardService getRewordServiceByType(Integer rewordType){
if(rewordType == null){
return null;
}
if(rewordType == 1){
return new ECardRewardService();
}
if(rewordType == 2){
return new MaterialRewardService();
}
if(rewordType == 3){
return new VirtualRewardService();
}
throw new RuntimeException("不存在的奖励类型");
}
public RewardService getRewordServiceByClazz(Class<? extends RewardService> clazz){
if (clazz == null){
return null;
}
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
可以看到,在这个方法中,提供了两个方法,一个通过类型返回service对象,一个通过Class类型返回对象,下面是对应的测试代码:
public class SimpleFactoryTests {
@Test
public void testGetRewordServiceByType(){
SimpleFactory simpleFactory = new SimpleFactory();
RewardService rewardService = simpleFactory.getRewordServiceByType(2);
rewardService.giveReword(222L,333L,"reword2",new HashMap<>());
}
@Test
public void testGetRewordServiceByClazz(){
SimpleFactory simpleFactory = new SimpleFactory();
RewardService rewardService = simpleFactory.getRewordServiceByClazz(VirtualRewardService.class);
rewardService.giveReword(444L,555L,"reword3",new HashMap<>());
}
}
就这其实就实现了一个最简单的工厂方法了,但是离我们用到实际工作中其实还差的很远,因为实际工作的,我们会更多的与Spring去结合使用,那看看我平常都是怎么写的吧~
首先定义工厂配置类,用于职责隔离
public class RewardConfig {
protected static Map<Constants.REWARD, RewardSpringService> factoryMap = new ConcurrentHashMap<>();
@Resource
private ECardRewardSpringService eCardRewardSpringService;
@Resource
private MaterialRewardSpringService materialRewardSpringService;
@Resource
private VirtualRewardSpringService virtualRewardSpringService;
@PostConstruct
public void init(){
factoryMap.put(Constants.REWARD.VIRTUAL_REWORD,virtualRewardSpringService);
factoryMap.put(Constants.REWARD.MATERIAL_REWOD,materialRewardSpringService);
factoryMap.put(Constants.REWARD.ECARD_REWORD,eCardRewardSpringService);
}
}
其次,定义工厂类继承于配置类,给出获取service的方法
@Service
public class RewardFactory extends RewardConfig{
public RewardSpringService getRewardService(Constants.REWARD rewardType){
return factoryMap.get(rewardType);
}
}
@Configuration
public class RewardContext {
/**
* 利用Spring依赖注入的第一种方式
* @param eCardRewardSpringService
* @param materialRewardSpringService
* @param virtualRewardSpringService
* @return
*/
@Bean
public Map<Constants.REWARD, RewardSpringService> getRewardMap(ECardRewardSpringService eCardRewardSpringService,
MaterialRewardSpringService materialRewardSpringService,
VirtualRewardSpringService virtualRewardSpringService){
Map<Constants.REWARD,RewardSpringService> rewardFactoryMap = new HashMap<>(8);
rewardFactoryMap.put(Constants.REWARD.ECARD_REWORD,eCardRewardSpringService);
rewardFactoryMap.put(Constants.REWARD.MATERIAL_REWOD,materialRewardSpringService);
rewardFactoryMap.put(Constants.REWARD.VIRTUAL_REWORD,virtualRewardSpringService);
return rewardFactoryMap;
}
}
首先也是定义配置类
public class RewardConfig {
@Resource
private List<RewardSpringService> rewardList;
public Map<Constants.REWARD, RewardSpringService> getRewardAutoWireMap() {
return rewardAutoWireMap;
}
protected static Map<Constants.REWARD,RewardSpringService> rewardAutoWireMap = new ConcurrentHashMap<>();
@PostConstruct
private void init(){
rewardList.forEach(reward ->{
Strategy strategy = AnnotationUtils.findAnnotation(reward.getClass(),Strategy.class);
if(strategy != null){
rewardAutoWireMap.put(strategy.rewardType(),reward);
}
});
}
}
其次定义工厂类继承于配置类:
@Service
public class RewardAutowire extends RewardConfig{
public void getReward(){
RewardSpringService rewardSpringService = rewardAutoWireMap.get(Constants.REWARD.VIRTUAL_REWORD);
rewardSpringService.giveReword(555L,666L,"reward_003",new HashMap<>());
}
}
@SpringBootTest
public class SpringFactoryTests {
@Resource
private RewardFactory rewardFactory;
@Resource
private Map<Constants.REWARD, RewardSpringService> rewardMap;
@Resource
private RewardAutowire rewardAutowire;
@Test
public void getReward1(){
RewardSpringService rewardSpringService = rewardFactory.getRewardService(Constants.REWARD.ECARD_REWORD);
rewardSpringService.giveReword(111L,222L,"reward_001",new HashMap<>());
}
@Test
public void getReward2(){
RewardSpringService rewardSpringService = rewardMap.get(Constants.REWARD.MATERIAL_REWOD);
rewardSpringService.giveReword(333L,444L,"reward_002",new HashMap<>());
}
@Test
public void getReward3(){
RewardSpringService rewardSpringService = rewardAutowire.getRewardAutoWireMap().get(Constants.REWARD.VIRTUAL_REWORD);
rewardSpringService.giveReword(555L,666L,"reward_003",new HashMap<>());
}
}
在本博客中,讲述了几种工作中常用的实现工厂模式的方式(结合Spring),分别是:
相信总有一款适合大家