锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

JAVA【设计模式】工厂方法模式

时间:2022-08-13 13:30:03 aqy212eh继电器aqy230sz继电器光耦继电器aqy211eha

工厂方法模式

  • 一、定义
  • 二、示例:
      • 传统硬编码方式(都在一个类里面实现,多重if else嵌套使用)
      • 工厂方法模式设计

一、定义

在这里插入图片描述

??模式?称???法模式,是?种创建设计模式,提供创建对象的法律, 允许?类
决定实例对象的类型。

这种设计模式也是如此 Java 其主要意图是开发最常见的模式定义创建对象的连接,让其? 类决定实例化哪个类,模式将其创建过程延迟到类进。

简单地说,它是为了提供代码结构的可扩展性,每个功能类屏蔽的具体实现逻辑。让外面更简单的就是知道如何调整?同时,它也消除了很多 ifelse 当然,如果需要,这也可能有一些缺点实现的类别很多,如何维护,如何降低开发成本。但在后续的设计模式下,这些问题可以逐渐减少。

二、示例:

模拟场景:
1.比如一般找对象的方式就是自己认识新女生,类似女生。需要自己new出来。假设有一个媒人牵线平台,你只需要说出你想要什么样的女孩,平台会给你连线什么样的女孩?
2.例如,当商店被定义为工厂时,我需要在商店里兑换奖品。奖品类型包括爱奇艺兑换卡、实物商品、优惠券等。如果我想兑换实物商品,我只需要在商店里获得实物商品的对象,而不需要关心如何创建实物商品类别。

爱奇艺卡券:IQiYiCard

package com.qf.design.create.factorymethod.entity.card;  /** * @description 模拟爱奇艺视频卡,对象类 */ public class IQiYiCard { 
               // 卡券的一些信息  }  

获得爱奇艺卡券:IQiYiCardService

package com.qf.design.create.factorymethod.entity.card;  /** * @description 模拟爱奇艺会员卡服务 */ public class IQiYiCardService { 
              public void grantToken(String bindMobileNumber, String cardId) { 
                 System.out.println("一张爱奇艺会员卡模拟发放:"   bindMobileNumber   ","   cardId);     }  }  

优惠券类:CouponInfo

package com.qf.design.create.factorymethod.entity.coupon;  /** * @description 模拟优惠券,对象类 */ public class CouponInfo { 
              // 一些关于优惠券的信息  }  

优惠券服务: CouponService

package com.qf.design.create.factorymethod.entity.coupon;

/** * @description 模拟优惠券服务 */
public class CouponService { 
         

    public CouponResult sendCoupon(String uId, String couponNumber, String uuid) { 
         
        System.out.println("模拟发放优惠券一张:" + uId + "," + couponNumber + "," + uuid);
        return new CouponResult("0000", "发放成功");
    }

}

优惠券返回结果类:CouponResult

package com.qf.design.create.factorymethod.entity.coupon;

/** * @description 优惠券返回结果类 */
public class CouponResult { 
         

    private String code; // 编码
    private String info; // 描述

    public CouponResult(String code, String info) { 
         
        this.code = code;
        this.info = info;
    }

    public String getCode() { 
         
        return code;
    }

    public void setCode(String code) { 
         
        this.code = code;
    }

    public String getInfo() { 
         
        return info;
    }

    public void setInfo(String info) { 
         
        this.info = info;
    }
}

商品信息:GoodsInfo

package com.qf.design.create.factorymethod.entity.goods;

/** * @description 模拟商品信息,对象类 */
public class GoodsInfo { 
         
}

获取实物商品服务:GoodsService

package com.qf.design.create.factorymethod.entity.goods;

import com.alibaba.fastjson.JSON;

/** * @description 模拟实物商品服务 */
public class GoodsService { 
         

    public Boolean deliverGoods(DeliverReq req) { 
         
        System.out.println("模拟发货实物商品一个:" + JSON.toJSONString(req));
        return true;
    }

}

实物商品服务返回结果:DeliverReq

package com.qf.design.create.factorymethod.entity.goods;

public class DeliverReq { 
         

    private String userName;              // 用户姓名
    private String userPhone;             // 用户手机
    private String sku;                   // 商品SKU
    private String orderId;               // 订单ID
    private String consigneeUserName;     // 收货人姓名
    private String consigneeUserPhone;    // 收货人手机
    private String consigneeUserAddress;  // 收获人地址

    public String getUserName() { 
         
        return userName;
    }

    public void setUserName(String userName) { 
         
        this.userName = userName;
    }

    public String getUserPhone() { 
         
        return userPhone;
    }

    public void setUserPhone(String userPhone) { 
         
        this.userPhone = userPhone;
    }

    public String getSku() { 
         
        return sku;
    }

    public void setSku(String sku) { 
         
        this.sku = sku;
    }

    public String getOrderId() { 
         
        return orderId;
    }

    public void setOrderId(String orderId) { 
         
        this.orderId = orderId;
    }

    public String getConsigneeUserName() { 
         
        return consigneeUserName;
    }

    public void setConsigneeUserName(String consigneeUserName) { 
         
        this.consigneeUserName = consigneeUserName;
    }

    public String getConsigneeUserPhone() { 
         
        return consigneeUserPhone;
    }

    public void setConsigneeUserPhone(String consigneeUserPhone) { 
         
        this.consigneeUserPhone = consigneeUserPhone;
    }

    public String getConsigneeUserAddress() { 
         
        return consigneeUserAddress;
    }

    public void setConsigneeUserAddress(String consigneeUserAddress) { 
         
        this.consigneeUserAddress = consigneeUserAddress;
    }
}

传统硬编码方式(都在一个类里面实现,多重if else嵌套使用)

发奖请求对象:AwardReq

package com.qf.design.create.factorymethod.tradition;

import java.util.Map;

/** * @description 发奖请求对象 */
public class AwardReq { 
         

    private String uId;                 // 用户唯一ID
    private Integer awardType;          // 奖品类型(可以用枚举定义);1优惠券、2实物商品、3第三方兑换卡(爱奇艺)
    private String awardNumber;         // 奖品编号;sku、couponNumber、cardId
    private String bizId;               // 业务ID,防重复
    private Map<String, String> extMap; // 扩展信息

    public String getuId() { 
         
        return uId;
    }

    public void setuId(String uId) { 
         
        this.uId = uId;
    }

    public Integer getAwardType() { 
         
        return awardType;
    }

    public void setAwardType(Integer awardType) { 
         
        this.awardType = awardType;
    }

    public String getAwardNumber() { 
         
        return awardNumber;
    }

    public void setAwardNumber(String awardNumber) { 
         
        this.awardNumber = awardNumber;
    }

    public String getBizId() { 
         
        return bizId;
    }

    public void setBizId(String bizId) { 
         
        this.bizId = bizId;
    }

    public Map<String, String> getExtMap() { 
         
        return extMap;
    }

    public void setExtMap(Map<String, String> extMap) { 
         
        this.extMap = extMap;
    }
}

发奖结果反馈对象:AwardRes

package com.qf.design.create.factorymethod.tradition;

/** * @description 发奖结果反馈对象 */
public class AwardRes { 
         

    private String code; // 编码
    private String info; // 描述

    public AwardRes(String code, String info) { 
         
        this.code = code;
        this.info = info;
    }

    public String getCode() { 
         
        return code;
    }

    public void setCode(String code) { 
         
        this.code = code;
    }

    public String getInfo() { 
         
        return info;
    }

    public void setInfo(String info) { 
         
        this.info = info;
    }

}

模拟发奖服务:PrizeController ,多重语句if else判断,代码功能实现了,但是不好后续的维护和扩展

package com.qf.design.create.factorymethod.tradition;

import com.alibaba.fastjson.JSON;
import com.qf.design.create.factorymethod.entity.card.IQiYiCardService;
import com.qf.design.create.factorymethod.entity.coupon.CouponResult;
import com.qf.design.create.factorymethod.entity.coupon.CouponService;
import com.qf.design.create.factorymethod.entity.goods.DeliverReq;
import com.qf.design.create.factorymethod.entity.goods.GoodsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** * @description 模拟发奖服务 */
public class PrizeController { 
         

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

    public AwardRes awardToUser(AwardReq req) { 
         
        String reqJson = JSON.toJSONString(req);
        AwardRes awardRes = null;
        try { 
         
            logger.info("奖品发放开始{}。req:{}", req.getuId(), reqJson);
            // 按照不同类型方法商品[1优惠券、2实物商品、3第三方兑换卡(爱奇艺)]
            if (req.getAwardType() == 1) { 
         
                CouponService couponService = new CouponService();
                CouponResult couponResult = couponService.sendCoupon(req.getuId(), req.getAwardNumber(), req.getBizId());
                if ("0000".equals(couponResult.getCode())) { 
         
                    awardRes = new AwardRes("0000", "发放成功");
                } else { 
         
                    awardRes = new AwardRes("0001", couponResult.getInfo());
                }
            } else if (req.getAwardType() == 2) { 
         
                GoodsService goodsService = new GoodsService();
                DeliverReq deliverReq = new DeliverReq();
                deliverReq.setUserName(queryUserName(req.getuId()));
                deliverReq.setUserPhone(queryUserPhoneNumber(req.getuId()));
                deliverReq.setSku(req.getAwardNumber());
                deliverReq.setOrderId(req.getBizId());
                deliverReq.setConsigneeUserName(req.getExtMap().get("consigneeUserName"));
                deliverReq.setConsigneeUserPhone(req.getExtMap().get("consigneeUserPhone"));
                deliverReq.setConsigneeUserAddress(req.getExtMap().get("consigneeUserAddress"));
                Boolean isSuccess = goodsService.deliverGoods(deliverReq);
                if (isSuccess) { 
         
                    awardRes = new AwardRes("0000", "发放成功");
                } else { 
         
                    awardRes = new AwardRes("0001", "发放失败");
                }
            } else if (req.getAwardType() == 3) { 
         
                String bindMobileNumber = queryUserPhoneNumber(req.getuId());
                IQiYiCardService iQiYiCardService = new IQiYiCardService();
                iQiYiCardService.grantToken(bindMobileNumber, req.getAwardNumber());
                awardRes = new AwardRes("0000", "发放成功");
            }
            logger.info("奖品发放完成{}。", req.getuId());
        } catch (Exception e) { 
         
            logger.error("奖品发放失败{}。req:{}", req.getuId(), reqJson, e);
            awardRes = new AwardRes("0001", e.getMessage());
        }

        return awardRes;
    }

    private String queryUserName(String uId) { 
         
        return "花花";
    }

    private String queryUserPhoneNumber(String uId) { 
         
        return "15200101232";
    }

}

测试:ApiTest

package com.qf.design.create.factorymethod.tradition;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;

public class ApiTest { 
         
    private static Logger logger = LoggerFactory.getLogger(ApiTest.class);
    public static void main(String[] args) { 
         
        PrizeController prizeController = new PrizeController();

        System.out.println("\r\n模拟发放优惠券测试\r\n");
        // 模拟发放优惠券测试
        AwardReq req01 = new AwardReq();
        req01.setuId("10001");
        req01.setAwardType(1);
        req01.setAwardNumber("EGM1023938910232121323432");
        req01.setBizId("791098764902132");
        AwardRes awardRes01 = prizeController.awardToUser(req01);

        logger.info("请求参数:{}", JSON.toJSON(req01));
        logger.info("测试结果:{}", JSON.toJSON(awardRes01));

        System.out.println("\r\n模拟方法实物商品\r\n");
        // 模拟方法实物商品
        AwardReq req02 = new AwardReq();
        req02.setuId("10001");
        req02.setAwardType(2);
        req02.setAwardNumber("9820198721311");
        req02.setBizId("1023000020112221113");
        req02.setExtMap(new HashMap<String, String>() { 
         { 
         
            put("consigneeUserName", "谢飞机");
            put("consigneeUserPhone", "15200292123");
            put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
        }});

        AwardRes awardRes02 = prizeController.awardToUser(req02);
        logger.info("请求参数:{}", JSON.toJSON(req02));
        logger.info("测试结果:{}", JSON.toJSON(awardRes02));

        System.out.println("\r\n第三方兑换卡(爱奇艺)\r\n");
        AwardReq req03 = new AwardReq();
        req03.setuId("10001");
        req03.setAwardType(3);
        req03.setAwardNumber("AQY1xjkUodl8LO975GdfrYUio");

        AwardRes awardRes03 = prizeController.awardToUser(req03);
        logger.info("请求参数:{}", JSON.toJSON(req03));
        logger.info("测试结果:{}", JSON.toJSON(awardRes03));
    }
}

工厂方法模式设计

定义一个奖品的接口:ICommodity ,所有的奖品都实现此接口

package com.qf.design.create.factorymethod.design;

import java.util.Map;

/** * 发送奖品接口 */
public interface ICommodity { 
         
    /** * private String uId; // 用户唯一ID * private Integer awardType; // 奖品类型(可以用枚举定义);1优惠券、2实物商品、3第三方兑换卡(爱奇艺) * private String awardNumber; // 奖品编号;sku、couponNumber、cardId * private String bizId; // 业务ID,防重复 * private Map extMap; // 扩展信息 * @param uId * @param awardNumber * @param bizId * @param extMap */
    void sendCommodity(String uId, String commodityId, String awardNumber, String bizId, Map<String, String> extMap);
}

爱奇艺卡片:CardCommodityService

package com.qf.design.create.factorymethod.design;

import com.alibaba.fastjson.JSON;
import com.qf.design.create.factorymethod.entity.card.IQiYiCardService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class CardCommodityService implements ICommodity { 
         


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

    // 模拟注入
    private IQiYiCardService iQiYiCardService = new IQiYiCardService();

    @Override
    public void sendCommodity(String uId, String commodityId, String awardNumber, String bizId, Map<String, String> extMap) { 
         
        String mobile = queryUserMobile(uId);
        iQiYiCardService.grantToken(mobile, bizId);
        logger.info("请求参数[爱奇艺兑换卡] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap));
        logger.info("测试结果[爱奇艺兑换卡]:success");
    }

    private String queryUserMobile(String uId) { 
         
        return "15200101232";
    }
}

优惠卷:CouponCommodityService

package com.qf.design.create.factorymethod.design;

import com.alibaba.fastjson.JSON;
import com.qf.design.create.factorymethod.entity.coupon.CouponResult;
import com.qf.design.create.factorymethod.entity.coupon.CouponService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class CouponCommodityService implements ICommodity  { 
         

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

    private CouponService couponService = new CouponService();

    @Override
    public void sendCommodity(String uId, String commodityId, String awardNumber, String bizId, Map<String, String> extMap) { 
         
        CouponResult couponResult = couponService.sendCoupon(uId, commodityId, bizId);
        logger.info("请求参数[优惠券] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap));
        logger.info("测试结果[优惠券]:{}", JSON.toJSON(couponResult));
        if (!"0000".equals(couponResult.getCode())) throw new RuntimeException(couponResult.getInfo());
    }
}

商品实体:GoodsCommodityService

package com.qf.design.create.factorymethod.design;

import com.alibaba.fastjson.JSON;
import com.qf.design.create.factorymethod.entity.goods.DeliverReq;
import com.qf.design.create.factorymethod.entity.goods.GoodsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class GoodsCommodityService implements ICommodity  { 
         

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

    private GoodsService goodsService = new GoodsService();

    @Override
    public void sendCommodity(String uId, String commodityId, String awardNumber, String bizId, Map<String, String> extMap) { 
         
        DeliverReq deliverReq = new DeliverReq();
        deliverReq.setUserName(queryUserName(uId));
        deliverReq.setUserPhone(queryUserPhoneNumber(uId));
        deliverReq.setSku(commodityId);
        deliverReq.setOrderId(bizId);
        deliverReq.setConsigneeUserName(extMap.get("consigneeUserName"));
        deliverReq.setConsigneeUserPhone(extMap.get("consigneeUserPhone"));
        deliverReq.setConsigneeUserAddress(extMap.get("consigneeUserAddress"));

        Boolean isSuccess = goodsService.deliverGoods(deliverReq);

        logger.info("请求参数[实物商品] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap));
        logger.info("测试结果[实物商品]:{}", isSuccess);

        if (!isSuccess) throw new RuntimeException("实物商品发放失败");
    }

    private String queryUserName(String uId) { 
         
        return "花花";
    }

    private String queryUserPhoneNumber(String uId) { 
         
        return "15200101232";
    }
}

商店,工厂:StoreFactory

package com.qf.design.create.factorymethod.design;

import com.qf.design.create.factorymethod.entity.card.IQiYiCardService;

/** * 实例化工厂 */
public class StoreFactory { 
         

    public ICommodity getCommodityService(int type){ 
         
        switch (type){ 
         
            case 1:
                return new CouponCommodityService();
            case 2:
                return new GoodsCommodityService();
            case 3:
                return new CardCommodityService();
        }
        throw new RuntimeException("不存在的奖品服务类型");
    }

    public ICommodity getCommodityClass(Class<? extends ICommodity> clazz) throws IllegalAccessException, InstantiationException { 
         
        if (clazz==null)return null;
        return  clazz.newInstance();
    }
}

测试:ApiTest

package com.qf.design.create.factorymethod.design;

import org.junit.jupiter.api.Test;

import java.util.HashMap;

public class ApiTest { 
         

    @Test
    public void test_StoreFactory_01() throws Exception { 
         
        StoreFactory storeFactory = new StoreFactory();

        // 1. 优惠券
        ICommodity commodityService_1 = storeFactory.getCommodityService(1);
        commodityService_1.sendCommodity("10001", "EGM1023938910232121323432", null, "791098764902132",null);

        // 2. 实物商品
        ICommodity commodityService_2 = storeFactory.getCommodityService(2);
        commodityService_2.sendCommodity("10001", "9820198721311", null, null,new HashMap<String, String>() { 
         { 
         
            put("consigneeUserName", "谢飞机");
            put("consigneeUserPhone", "15200292123");
            put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
        }});

        // 3. 第三方兑换卡(模拟爱奇艺)
        ICommodity commodityService_3 = storeFactory.getCommodityService(3);
        commodityService_3.sendCommodity("10001", "AQY1xjkUodl8LO975GdfrYUio", null, null,null);

    }

    @Test
    public void test_StoreFactory_02() throws Exception { 
         
        StoreFactory storeFactory = new StoreFactory();
        // 1. 优惠券
        ICommodity commodityService = storeFactory.getCommodityClass(CouponCommodityService.class);
        commodityService.sendCommodity("10001", "EGM1023938910232121323432", "791098764902132", null,null);

        // 2. 实物商品
        ICommodity commodityService_2 = storeFactory.getCommodityClass(GoodsCommodityService.class);
        commodityService_2.sendCommodity("10001", "9820198721311", null, null,new HashMap<String, String>() { 
         { 
         
            put("consigneeUserName", "谢飞机");
            put("consigneeUserPhone", "15200292123");
            put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
        }});

        // 3. 第三方兑换卡(模拟爱奇艺)
        ICommodity commodityService_3 = storeFactory.getCommodityClass(CardCommodityService.class);
        commodityService_3.sendCommodity("10001", "AQY1xjkUodl8LO975GdfrYUio", null, null,null);
    }
}

总结:
避免创建者与具体的产品逻辑耦合 、 满⾜单⼀职责,每⼀个业务逻辑实现都在所属⾃⼰的类中完成 、 满⾜开闭原则⽆需更改使⽤调⽤⽅就可以在程序中引⼊新的产品类型 。但这样也会带来⼀些问题,⽐如有⾮常多的奖品类型,那么实现的⼦类会极速扩张。因此也需要使⽤其他的模式进⾏优化,这些在后续的设计模式中会逐步涉及到

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章