第九周_S-设计模式入场:创建型模式_工厂模式

557 阅读4分钟

基本上,大家都能说上两句设计模式的事,其他不说,单例模式总该知道吧。设计模式是由多年的经验提炼出来开发指导思想。今天开启设计模式系列的学习:

创建型模式之工厂模式:

概念:工厂模式又称工厂方法模式,是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。即对象创建过程延迟到子类实现。

提供了代码的扩展性,屏蔽了每一个功能类中的具体实现逻辑。外部只需调用即可,可以去掉众多的 if-else 。

案例

购买商品(会员),比如 饿了吗/美团/饿了吗+网易云组合。

直接实现功能

首先是满足需求的,而且按时完成了任务,还完成的很快。

但是如果,我现在需要新增需求,加一个:美团+网易云组合。那得改主要逻辑类,而且都得回归测试,因为你懂了主要得逻辑类。所以,以前写的都必须重新测试。显然不合理。

import com.alibaba.fastjson.JSON;
import com.practic.thinkinpatterndesign.工厂模式.CommonReq;
import com.practic.thinkinpatterndesign.工厂模式.CommonRes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class CommonController {

    private Logger logger = LoggerFactory.getLogger(CommonController.class);


    public CommonRes CommonBuy(CommonReq req) {
        String reqJson = JSON.toJSONString(req);
        try {
             logger.info("客户购买开始:{},req:{}",req.getBuyBusiId(),reqJson);
             //按照不同的类型组合商品//1.饿了吗;2.美团;3.饿了吗+网易云
            if(req.getBuyType()==1){
                //对接饿了吗系统
                System.out.println("单独购买饿了吗:成功");
                return CommonRes.ok("单独购买饿了吗成功:"+req.getBuyBusiId());
            }else if(req.getBuyType()==2){
                //对接美团系统
                System.out.println("单独购买美团:成功");
                return CommonRes.ok("单独购买美团成功:"+req.getBuyBusiId());
            }else if(req.getBuyType()==3){
                //对接饿了吗系统+网易云
                System.out.println("组合购买饿了吗+网易云:成功");
                return CommonRes.ok("组合购买饿了吗+网易云成功:"+req.getBuyBusiId());
            }
        } catch (Exception e) {
            logger.error("购买失败:{},req:{}",req.getBuyBusiId(),reqJson);
            return CommonRes.error();
        }
        return CommonRes.ok("成功");
    }
import lombok.Data;

@Data
public class CommonReq {
    private String buyBusiId;  //订单流水号
    private int buyType;    //订单关联的商品类型
    private int userId;     //用户唯一id
}
import lombok.Data;
import java.util.HashMap;
import java.util.Objects;

@Data
public class CommonRes extends HashMap<String, Object> {
    private int code;
    private String msg;
    private Object data;

    private static final String MSG_SUCCESS = "成功";
    private static final int CODE_SUCCESS = 0;
    private static final String MSG_FAIL = "失败";
    private static final int CODE_FAIL = 1;

    public CommonRes(int code, String msg) {
        super.put("code", code);
        super.put("msg", msg);
    }

    public CommonRes(int code, String msg, Object data) {
        super.put("code", code);
        super.put("msg", msg);
        if (!Objects.isNull(data)) {
            super.put("data", data);
        }
    }

    /**
     * 成功返回示例
     */
    public static CommonRes ok() {
        return new CommonRes(CODE_SUCCESS, MSG_SUCCESS,null);
    }

    public static CommonRes ok(String msg) {
        return new CommonRes(CODE_SUCCESS, msg,null);
    }

    public static CommonRes ok(Object data) {
        return new CommonRes(CODE_SUCCESS, MSG_SUCCESS, data);
    }

    public static CommonRes ok(String msg, Object data) {
        return new CommonRes(CODE_SUCCESS, msg, data);
    }


    /**
     * 失败返回示例
     */
    public static CommonRes error() {
        return new CommonRes(CODE_FAIL, MSG_FAIL,null);
    }

    public static CommonRes error(String msg) {
        return new CommonRes(CODE_FAIL, msg,null);
    }

    public static CommonRes error(String msg, Object data) {
        return new CommonRes(CODE_FAIL, msg, data);
    }

}
     @Test
     public void test_buy(){
         CommonController commonController=new CommonController();
         System.out.println("模拟购买商品====");
         //业务类型为 1
         CommonReq req1=new CommonReq();
         req1.setBuyType(1);
         req1.setBuyBusiId("20221112093689123423");
         req1.setUserId(67855);
         CommonRes res1=commonController.CommonBuy(req1);
         logger.info("请求参数:{}", JSON.toJSONString(req1));
         logger.info("测试结果:{}",JSON.toJSONString(res1));
         //业务类型为 2
         CommonReq req2=new CommonReq();
         req2.setBuyType(2);
         req2.setBuyBusiId("20221112093689123423");
         req2.setUserId(67855);
         CommonRes res2=commonController.CommonBuy(req2);
         logger.info("请求参数:{}", JSON.toJSONString(req2));
         logger.info("测试结果:{}",JSON.toJSONString(res2));

     }

工厂方法

一个购买接口

public interface BuyService {
    public CommonRes buyCommon(CommonReq req);
}

各种具体的实现:这里是三个实现

public class MTbuyServiceImpl implements BuyService {
    private Logger logger = LoggerFactory.getLogger(MTbuyServiceImpl.class);
    @Override
    public CommonRes buyCommon(CommonReq req) {
        logger.info("美团入参:{}", JSON.toJSONString(req));
        //1.获取用户,生成流水号,拼接入参
        //2.调用美团系统,处理逻辑
        //3.返回
        return CommonRes.ok("美团购买成功");
    }
}
public class ELMbuyServiceImpl implements BuyService {
    private Logger logger = LoggerFactory.getLogger(ELMbuyServiceImpl.class);
    @Override
    public CommonRes buyCommon(CommonReq req) {
        logger.info("饿了吗入参:{}", JSON.toJSONString(req));
        //1.获取用户,生成流水号,拼接入参
        //2.调用饿了吗系统,处理逻辑
        //3.返回

        return CommonRes.ok("饿了吗购买成功");
    }
}
public class ELMandWYYbuyServiceImpl implements BuyService {
    private Logger logger = LoggerFactory.getLogger(ELMandWYYbuyServiceImpl.class);
    @Override
    public CommonRes buyCommon(CommonReq req) {
        logger.info("饿了吗+网易云入参:{}", JSON.toJSONString(req));
        //1.获取用户,生成流水号,拼接入参
        //2.调用饿了吗+网易云系统,处理逻辑
        //3.返回
        return CommonRes.ok("饿了吗+网易云购买成功");
    }
}

工厂类:统一处理

public class StoreFactory {
    public BuyService getBuy(int buyType) {
        if (buyType == 1) {
            return new ELMbuyServiceImpl();
        }
        if (buyType == 2) {
            return new MTbuyServiceImpl();
        }
        if (buyType == 3) {
            return new ELMandWYYbuyServiceImpl();
        }
        throw new RuntimeException("不存在商品类型");
    }
}

测试类:

    @Test
    public void test_buy(){
        //懒得写入参了,就这一个吧 0.0
        CommonReq req1=new CommonReq();
        req1.setBuyType(1);
        req1.setBuyBusiId("20221112093689123423");
        req1.setUserId(67855);

        StoreFactory factory = new StoreFactory();
        BuyService buyService1 = factory.getBuy(1);
        CommonRes res1 = buyService1.buyCommon(req1);
        logger.info("购买饿了吗成功:{}", JSON.toJSONString(res1));

        BuyService buyService2 = factory.getBuy(2);
        CommonRes res2 = buyService2.buyCommon(req1);
        logger.info("购买美团成功:{}",JSON.toJSONString(res2));

        BuyService buyService3 = factory.getBuy(3);
        CommonRes res3 = buyService3.buyCommon(req1);
        logger.info("购买饿了吗+网易云成功:{}",JSON.toJSONString(res3));

    }

我们将具体实现推迟到子类实现,这里很方便的是:如果新增需求,只需要写一个实现购买方法的接口即可。

而且不用回归测试其他原来已经写好的需求,因为都没有动。

思考:这里的工厂类,其实还是一个 if-else。但是可以将工厂类也做成一个接口,然后推迟到子类实现。

这样的做法就是避免了高耦合,但是类膨胀了(增加了额外的子类实现)

总结

不使用工厂工厂模式
开发快,开发逻辑清晰明了,一个类解决问题低耦合,利于扩展,结构也清晰明了
高度耦合,不利于拓展类膨胀

参考

www.cnblogs.com/zuoxiaolong…