Java工厂模式应用

1.1 案例需求

假设对于学校使用仪器要进行网上收费,然后学校可根据不同主体,比如课题组或者个人进行收费。也具有不同的收费模式。那么对于原先的代码来说需要进行多个if-else判断,代码示例如下:

public void chargeBackAndReturnResult(String chargeType,String chargeBody) {
        if(chargeBody.equals("Personal")){
            if(chargeType.equals("Credit")){
                System.out.println("执行收费主体为个人的信用卡收费模式");//真实业务代码有200行左右
            }else if(chargeType.equals(" deposit")){
                System.out.println("执行收费主体为个人的储蓄卡收费模式");
            }
        }else if(chargeBody.equals("CommonTeam")){
            if(chargeType.equals("Credit")){
                System.out.println("执行收费主体为课题组的信用卡收费模式");
            }else if(chargeType.equals(" deposit")){
                System.out.println("执行收费主体为课题组的储蓄卡收费模式");
            }
        }
    }

对于这种if-else嵌套来说,即使进行方法的封装,依然不利于程序扩展,并且如果增加收费主体和收费类型,则需要继续增加if-else嵌套,影响代码的可读性。

1.2 优化方案

可以明确的是,对于不同的收费主体以及收费模式,所传入的参数基本相同。无外乎用户/课题组编号,金额等基本业务内容。那么我们就可以将收费模式统一抽象出一种行为规范作为接口,并通过不同实现类对接口进行继承。然后通过工厂进行统一管理,这就是工厂模式的核心思想。

1.2.1 接口的创建

    public interface ChargeService {
        String getType();//用于获取收费类型
        String chargeBackAndReturnResult();//用于执行具体收费方法
    }

1.2.2 实现类的创建

public class DepositPersonalChargeServiceImpl implements ChargeService{
    public String getType(){
        return "DepositPersonal";
    }
    public void chargeBackAndReturnResult() {
        System.out.println("执行收费主体为个人的借记卡收费模式");
    }
}

public class DepositCommonTeamChargeServiceImpl implements ChargeService{
    public String getType(){
        return "DepositCommonTeam";
    }
    public void chargeBackAndReturnResult() {
        System.out.println("执行收费主体为课题组的借记卡收费模式");
    }
}

public class CreditPersonalChargeServiceImpl implements ChargeService{
    public String getType(){
        return "CreditPersonal";
    }
    public void chargeBackAndReturnResult() {
        System.out.println("执行收费主体为个人的信用卡收费模式");
    }
}
public class CreditCommonTeamChargeServiceImpl implements ChargeService{
    public String getType(){
        return "CreditCommonTeam";
    }
    public void chargeBackAndReturnResult() {
        System.out.println("执行收费主体为课题组的信用卡收费模式");
    }
}

1.2.3 工厂的创建

public class ChargeFactory{
    public static Map<String,ChargeService> chargeMap=new HashMap<String,ChargeService>();//定义一个map容器

    static{
        chargeMap.put("DepositCommonTeam",new DepositCommonTeamChargeServiceImpl());
        chargeMap.put("DepositPersonal",new DepositPersonalChargeServiceImpl());
        chargeMap.put("CreditPersonal",new CreditPersonalChargeServiceImpl());
        chargeMap.put("CreditCommonTeam",new CreditCommonTeamChargeServiceImpl());
    }//写入map的值

    public static ChargeService getChargeService(String chargeType){
        ChargeService chargeService=chargeMap.get(chargeType);
        if(chargeService!=null){
            return chargeService;
        }else{
            return null;
        }
    }
}

1.2.4 测试用例

  public static void main(String[] args){
        ChargeService chargeService=ChargeFactory.getChargeService("DepositCommonTeam");//获取对应的Service对象
        chargeService.chargeBackAndReturnResult();//调用对应的方法
    }

输出结果

执行收费主体为课题组的借记卡收费模式

2 利用SpringBoot框架进行进一步优化

2.1 之前方案所存在的不足

对于案例给出的解决方案来说,存在两个缺点:

新策略添加时,不仅需要增添新的class类,还需要在Factory工厂进行对应class的添加。
参照mvc经典框架下实现代码:

//Service实现层
@Service
public class DepositCommonTeamChargeServiceImpl implements ChargeService{
    @Autowired
    UserService userService;
    public String getType(){
        return "DepositCommonTeam";
    }
    public void chargeBackAndReturnResult() {
        if(userService==null){
            System.out.println("User服务注入失败");
        }else{
            System.out.println("User服务注入成功");
        }
        System.out.println("执行收费主体为课题组的借记卡收费模式");
    }
}
//Controller层
@RestController
public class Test {
    @RequestMapping(value = "/charge/test",method = RequestMethod.POST)
    public void test(){//经典mvc框架Controller层调用Service方法
        ChargeService chargeService=ChargeFactory.getChargeService("DepositCommonTeam");
        chargeService.chargeBackAndReturnResult();
    }
}

输出结果

User服务注入失败
执行收费主体为课题组的借记卡收费模式

能够发现如果应用@Autowired注解所注入的Spring对象,在方法调用时无法获取到。

2.2 优化解决方案

修改原Factory工厂类

@Component
public class ChargeFactory implements ApplicationContextAware {
    public static Map<String,ChargeService> chargeMap=new HashMap<String,ChargeService>();//定义一个Map类
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //根据接口类型返回相应的所有bean
        Map<String, ChargeService> map = applicationContext.getBeansOfType(ChargeService.class);//通过applicationContext获取注入Spring容器中的类
        map.forEach((key, value) -> chargeMap.put(value.getType(), value));//给Map类进行赋值
    }
    
    public static ChargeService getChargeService(String chargeType){
        ChargeService chargeService=chargeMap.get(chargeType);
        if(chargeService!=null){
            return chargeService;
        }else{
            return null;
        }
    }
}

此时再进行结果输出

User服务注入成功
执行收费主体为课题组的借记卡收费模式

参考:https://blog.csdn.net/weixin_39174824/article/details/99306446?app_version=5.14.1&csdn_share_tail={"type"%3A"blog"%2C"rType"%3A"article"%2C"rId"%3A"99306446"%2C"source"%3A"m0_71913150"}&utm_source=app

posted @ 2023-02-20 09:41  离人怎挽_wdj  阅读(33)  评论(0编辑  收藏  举报