如何在springboot中合理使用工厂模式(你真的会在实际业务中应用设计模式吗?)

如何在springboot中合理使用工厂模式-工厂模式

      • 工厂模式优点:
      • 前言 请看如下工程结构实例:
      • 1、在工厂中声明的bean如何交给springboot管理
          • 方法一:使用 Spring 的 @Bean 方法来注册工厂方法
          • 方法二:使用 Spring 的 ApplicationContext 来获取 bean
          • 方法三:使用原型 bean(推荐)
      • 实现代码
        • 1、定义组件接口:
        • 2、不同的组件实现:
        • 3、创建工厂 通过抽象工厂注入不同的bean
        • 4、调用工厂实际使用

工厂模式优点:

避免创建者具体的产品逻辑耦合、满足单一职责,每一个业务逻辑实现都在所属自己的类中完成、满足开闭原则,无需更改使用调用方就可以在程序中引入新的产品类型。

前言 请看如下工程结构实例:

首先本工程简单实例业务场景下工厂模式的使用。
目标:实现不同的环节内容穿件不同的组件提供使用。
比如 A环节 环节内容包含

设计完成时间:时间选择框

设计负责人:输入框

设计资料上传: 文件上传

itstack-demo-design-1-02
└── src
├── main
│ └── java
│ └── org.itstack.demo.design
│ ├── store
│ │ ├── impl
│ │ │ ├── CompDateImpl.java
│ │ │ ├── CompFileDownImpl.java
│ │ │ └── CompSelectImpl.java
│ │ └── CompDefinitionInterFace.java
│ └── StoreFactory.java
└── use–<
└── java
└── IssueCompServiceImpl 《》
└── IssueCompService

1、在工厂中声明的bean如何交给springboot管理

假设你有一个CompFile工厂 实例 CompFileImpl 你使用 new 关键字在工厂方法中创建

方法一:使用 Spring 的 @Bean 方法来注册工厂方法

你可以将工厂方法本身标记为 @Bean,并让 Spring 容器来管理这些对象的创建。

方法二:使用 Spring 的 ApplicationContext 来获取 bean

你可以修改 StoreFactory 来获取 ApplicationContext 并从中查找相应的 bean。但请注意,可能导致代码难以测试和维护

方法三:使用原型 bean(推荐)

你可以将 CompFileImpl 声明为一个原型 bean,然后在工厂方法中请求 Spring 容器来为你创建新的实例。这样,每次通过工厂方法创建的 CompFileImpl 实例都会是 Spring 容器管理的,并且它们的依赖会被自动注入。@Scope(“prototype”) // 声明为原型 bean

 @Autowired  
    private ApplicationContext applicationContext;  
 return applicationContext.getBean(CompFileImpl.class);  
 
@Service  
@Scope("prototype") // 声明为原型 bean  
@Slf4j  
public class CompFileImpl implements CompDefinitionInterFace {  
    // ... 其他代码 ...  
}

实现代码

1、定义组件接口:
 
public interface CompDefinitionInterFace{

    /** 
    * * 方法描述:获取组件信息通过操作编号(含操作内容)  
    *
    */
    Object getCompByOperType(String operTypeValue);

  /**

   * 方法描述:通过操作编号获得组件信息(限制回显)
     *
   * @param appNo  工单编号
   * @param processNo 流程编号
   * @param operNo  操作环节编号 
     */
     Object getCompByOperNo(String appNo, String processNo, String operNo);

     Object getCompByOperNo(SpProcessOperDTO spProcessOperDTO);
  }
 
2、不同的组件实现:


import com.sgcc.issueambt.front.common.mapper.SpCodeMapper;
import com.sgcc.issueambt.front.common.model.dto.SpCodeDTO;
import com.sgcc.issueambt.front.common.model.vo.CodeConstant;
import com.sgcc.issueambt.front.issuecomp.model.bo.CompFileDownLoadBO;
import com.sgcc.issueambt.front.issuecomp.model.bo.CompFileUploadBO;
import com.sgcc.issueambt.front.issuecomp.model.vo.CompFileDownLoadVO;
import com.sgcc.issueambt.front.issueoper.mapper.SpProcessOperMapper;
import com.sgcc.issueambt.front.issueoper.model.dto.SpProcessOperDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
@Slf4j
public class CompFileDownImpl implements CompDefinitionInterFace {
    @Resource
    private SpCodeMapper spCodeMapper;
    @Resource
    private SpProcessOperMapper spProcessOperMapper;
    /**
 * 方法描述:获取组件信息通过操作编号(含操作内容)
 *
 * @param operTypeValue
 */
@Override
public Object getCompByOperType(String operTypeValue) {
    CompFileDownLoadBO compFileDownLoadBO = new CompFileDownLoadBO();
    SpCodeDTO spCodeDTO = spCodeMapper.selectFirstByTypeCodeAndCodeValue(CodeConstant.OPER_TYPE.getValue(), operTypeValue);
    compFileDownLoadBO.setOperType(operTypeValue);
    compFileDownLoadBO.setOperTypeName(spCodeDTO.getCodeName());
    compFileDownLoadBO.setRequired("1".equals(spCodeDTO.getLogoThree()));
    compFileDownLoadBO.setTitle(spCodeDTO.getLogoTwo());
    compFileDownLoadBO.setDownloadUrl(spCodeDTO.getLogoFour());
    return compFileDownLoadBO;
}

/**
 * 方法描述:通过操作编号获得组件信息(限制回显)
 *
 * @param appNo     工单编号
 * @param processNo 流程编号
 * @param operNo    操作环节编号
 * @return {@link Object }
 * @author xú chūn chéng
 * @since 1.0.0   2024-06-06 05:05:29
 */
@Override
public Object getCompByOperNo(String appNo, String processNo, String operNo) {
    CompFileDownLoadVO compFileDownLoadVO = new CompFileDownLoadVO();
    SpProcessOperDTO operate = spProcessOperMapper.selectFirstByAppNoAndProcessNoAndOperType(appNo, processNo, operNo);
    if (operate != null) {
        Object comp = getCompByOperType(operate.getOperType());
        if (comp instanceof CompFileDownLoadBO) {
            CompFileDownLoadBO compFileUploadBO = (CompFileDownLoadBO) comp;
            compFileDownLoadVO.setCompBO(compFileUploadBO);
        }
    }
    return compFileDownLoadVO;
}

@Override
public Object getCompByOperNo(SpProcessOperDTO operate) {
    CompFileDownLoadVO compFileDownLoadVO = new CompFileDownLoadVO();
    if (operate != null) {
        Object comp = getCompByOperType(operate.getOperType());
        if (comp instanceof CompFileDownLoadBO) {
            CompFileDownLoadBO compFileUploadBO = (CompFileDownLoadBO) comp;
            compFileDownLoadVO.setCompBO(compFileUploadBO);
        }
    }
    return compFileDownLoadVO;
}
}
3、创建工厂 通过抽象工厂注入不同的bean
import com.alibaba.fastjson.JSON;
import com.sgcc.issueambt.front.common.model.dto.SpCodeDTO;
import com.sgcc.issueambt.front.common.model.vo.CodeConstant;
import com.sgcc.issueambt.front.common.utils.StringUtil;
import com.sgcc.issueambt.front.common.utils.StringUtils;
import com.sgcc.issueambt.front.issuecomp.model.bo.CompTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class StoreFactory implements ApplicationContextAware {
    private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
}

public CompDefinitionInterFace getCommodityService(SpCodeDTO code) {
    if (code != null) {
        String operTxtType = StringUtils.getString(code.getLogoOne());
        if (StringUtil.isNullOrBlank(operTxtType)) {
            return applicationContext.getBean(CompSpecialImpl.class);

        }
        if (CompTypeEnum.OP_01_FILE_UPLOAD.getCode().equals(operTxtType))
            return applicationContext.getBean(CompFileUploadImpl.class);
        if (CompTypeEnum.OP_04_TEXT.getCode().equals(operTxtType))
            return applicationContext.getBean(CompTextImpl.class);
        if (CompTypeEnum.OP_05_SELECT_DOWN.getCode().equals(operTxtType)) {
            if (CodeConstant.OPER_TYPE_LJZSK.getValue().equals(code.getCodeValue())) {
                return applicationContext.getBean(CompLinkedKnowledgeImpl.class);
            }
            return applicationContext.getBean(CompSelectImpl.class);
        }
        if (CompTypeEnum.OP_06_TIME_DAY.getCode().equals(operTxtType))
            return applicationContext.getBean(CompDateImpl.class);
        if (CompTypeEnum.OP_10_CASCADING_DROP_DOWN_SELECTION_CH.getCode().equals(operTxtType)) {
            return applicationContext.getBean(CompLinkageSelectImpl.class);
        }
    }
    log.info("组件已经被移除{}", JSON.toJSONString(code));
    return applicationContext.getBean(CompSpecialImpl.class)
        }
}



4、调用工厂实际使用
@Resource
private StoreFactory storeFactory;

@Override
public Object getCreateComp(String operTypeValue) {
    SpCodeDTO code = spCodeMapper.selectFirstByTypeCodeAndCodeValue(CodeConstant.OPER_TYPE.getValue(), operTypeValue);
    CompDefinitionInterFace compDefinitionInterFace = storeFactory.getCommodityService(code);
    return compDefinitionInterFace.getCompByOperType(operTypeValue);
}

– 感觉不是很nice 希望各位指正。

你可能感兴趣的:(spring,boot,设计模式,后端)