创建型模式:工厂模式

文章目录

  • 创建型模式:工厂模式
    • 工厂模式
      • 1、工厂模式:介绍
      • 2、工厂模式:模拟场景
      • 3、工厂模式:代码实现
      • 4、工厂模式:总结

工厂模式

1、工厂模式:介绍

  • 工厂模式

    • 简单工厂模式,是创建型设计模式的一种,这种设计模式提供了按需创建对象的最佳方式。
    • 同时,这种创建方式不会对外暴露创建细节,并且会通过一个统一的接口创建所需对象。
  • 主要意图
    • 定义一个创建对象的接口,让其子类自己决定将哪一个工厂实例化
    • 工厂模式使创建过程延迟到子类中进行

2、工厂模式:模拟场景

  • 模拟互联网运营活动中营销场景的业务需求

    • 在营销场景中,经常会约定在用户完成打卡、分享、留言、邀请注册等一系列行为操作后进行返利积分操作。
    • 用户再通过这些返利积分兑换商品,从而让整个系统构成一个生态闭环,达到促活和拉新的目的。
序号 类型 接口
1 优惠券 CouponResult sendCoupon(String uId, String couponNumber, String uuid)
2 实物商品 Boolean deliverGoods(DeliverReq req)
3 第三方兑换卡(爱奇艺) void grantToken(String bindMobileNumber, String cardId)
  • 三种接口返回类型不同,有对象类型、布尔类型和空类型
  • 入参不同,发放优惠券需要仿重,兑换卡需要卡ID,实物商品需要发货位置(对象中含有)
  • 可能会随着后续业务的发展,新增其他的商品类型。因为所有的开发需求都是由业务对市场的拓展带来的。

3、工厂模式:代码实现

0、工程结构

lino-design-4.0
|——src|——main|--java|--com.lino|--product|  |--card|    |   |--IQiYiCardService.java|   |--coupon|  |   |--CouponResult|    |   |--CouponService|   |--goods|   |   |--DeliverReq|  |   |--GoodsService|--store|    |--impl|    |   |--CardCommodityServiceImpl|    |   |--CouponCommodityServiceImpl|  |   |--GoodsCommodityServiceImpl|   |--ICommodity.java|--StoreFactory.java|——test|--java|--com.lino.test|--Test.java

1、准备商品接口

优惠券

  • CouponResult
/*** @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;}
}
  • CouponService
/*** @description: 模拟优惠券服务*/
public class CouponService {public CouponResult sendCoupon(String uId, String couponNumber, String uuid) {System.out.println("模拟发放优惠券一张:" + uId + "," + couponNumber + "," + uuid);return new CouponResult("0000", "发放成功");}
}

实物商品

  • DeliverReq
/*** @description: 模拟请求参数*/
public class DeliverReq {/*** 用户姓名*/private String userName;/*** 用户手机*/private String userPhone;/*** 商品SKU*/private String sku;/*** 订单ID*/private String orderId;/*** 收货人姓名*/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;}
}
  • GoodsService
import com.alibaba.fastjson.JSON;/*** @description: 模拟实物商品服务*/
public class GoodsService {public Boolean deliverGoods(DeliverReq req) {System.out.println("模拟发货实物商品一个:" + JSON.toJSONString(req));return true;}
}

第三方兑换卡(爱奇艺)

  • IQiYiCardService
/*** @description: 模拟爱奇艺会员卡服务*/
public class IQiYiCardService {public void grantToken(String bindMobileNumber, String cardId) {System.out.println("模拟发放爱奇艺会员卡一张:" + bindMobileNumber + "," + cardId);}
}

2、定义发奖接口

  • 对于所有的奖品,无论是实物商品、优惠券还是第三方兑换卡(爱奇艺),都需要通过程序实现此接口并处理

    • 这样的方式可以保证入参和出参的统一性
  • 接口的入参
    • 用户ID,奖品ID,业务ID,扩展字段(用于处理发放实物商品时的收货地址)
import java.util.Map;/*** @description: 发奖接口*/
public interface ICommodity {/*** 发奖** @param uId         用户ID* @param commodityId 奖品ID* @param bizId       业务ID* @param extMap      扩展字段* @throws Exception 异常*/void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception;
}

3、实现三种发奖接口

  • 每一种奖品的实现都包装到自己的类中,当新增、修改或删除逻辑时,都不会影响其他奖品功能的测试。

  • 如果由新增的奖品,只需要按照此结构进行填充对应的实现类即可。易于维护和扩展。

  • 优惠券

import com.alibaba.fastjson.JSON;
import com.lino.product.coupon.CouponResult;
import com.lino.product.coupon.CouponService;
import com.lino.store.ICommodity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;/*** @description: 发放优惠券接口实现类*/
public class CouponCommodityServiceImpl implements ICommodity {/*** 日志*/private Logger logger = LoggerFactory.getLogger(CouponCommodityServiceImpl.class);/*** 优惠券服务对象*/private CouponService couponService = new CouponService();public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception {// 发放优惠券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());}}
}
  • 实物商品
import com.alibaba.fastjson.JSON;
import com.lino.product.goods.DeliverReq;
import com.lino.product.goods.GoodsService;
import com.lino.store.ICommodity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;/*** @description: 发放实物商品接口实现类*/
public class GoodsCommodityServiceImpl implements ICommodity {/*** 日志*/private Logger logger = LoggerFactory.getLogger(CouponCommodityServiceImpl.class);/*** 实物商品服务对象*/private GoodsService goodsService = new GoodsService();public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception {// 获取请求参数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("实物商品发放失败");}}/*** 根据用户ID返回用户名** @param uId 用户ID* @return 用户名*/private String queryUserName(String uId) {return "花花";}/*** 根据用户ID返回用户手机号** @param uId 用户ID* @return 用户手机号*/private String queryUserPhoneNumber(String uId) {return "15200101232";}
}
  • 第三方兑换卡(爱奇艺)
import com.alibaba.fastjson.JSON;
import com.lino.product.card.IQiYiCardService;
import com.lino.store.ICommodity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;/*** @description: 发放第三方兑换卡(爱奇艺)接口实现类*/
public class CardCommodityServiceImpl implements ICommodity {/*** 日志*/private Logger logger = LoggerFactory.getLogger(CouponCommodityServiceImpl.class);/*** 实物商品服务对象*/private IQiYiCardService iQiYiCardService = new IQiYiCardService();public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception {// 根据用户ID获取用户手机号String mobile = queryUserMobile(uId);// 发放爱奇艺兑换卡iQiYiCardService.grantToken(mobile, bizId);// 打印日志logger.info("请求参数[爱奇艺兑换卡] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap));logger.info("测试结果[爱奇艺兑换卡]:success");}/*** 根据用户ID获取用户手机号** @param uId 用户ID* @return 用户手机号*/private String queryUserMobile(String uId) {return "15200101232";}
}

4、创建商店工厂

  • 商店工厂实现类:提供两种获取工厂实现类的方法

    • 依赖奖品类型
    • 根据奖品类信息实例化
import com.lino.store.ICommodity;
import com.lino.store.impl.CardCommodityServiceImpl;
import com.lino.store.impl.CouponCommodityServiceImpl;
import com.lino.store.impl.GoodsCommodityServiceImpl;/*** @description: 商店工厂*/
public class StoreFactory {/*** 奖品类型方式实例化** @param CommodityType 奖品类型* @return 实例化对象*/public ICommodity getCommodityService(Integer CommodityType) {if (null == CommodityType) {return null;}if (1 == CommodityType) {return new CouponCommodityServiceImpl();}if (2 == CommodityType) {return new GoodsCommodityServiceImpl();}if (3 == CommodityType) {return new CardCommodityServiceImpl();}throw new RuntimeException("不存在的奖品服务类型");}/*** 奖品类信息方式实例化** @param clazz 奖品类型* @return 实例化对象* @throws IllegalAccessException 异常* @throws InstantiationException 异常*/public ICommodity getCommodityService(Class<? extends ICommodity> clazz) throws IllegalAccessException, InstantiationException {if (null == clazz) {return null;}return clazz.newInstance();}}

5、单元测试

import com.lino.StoreFactory;
import com.lino.store.ICommodity;
import com.lino.store.impl.CouponCommodityServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;/*** @description: 测试类*/
public class Test {private Logger logger = LoggerFactory.getLogger(Test.class);@org.junit.Testpublic void testStoreFactory01() throws Exception {StoreFactory storeFactory = new StoreFactory();// 1、优惠券ICommodity commodityService1 = storeFactory.getCommodityService(1);commodityService1.sendCommodity("10001", "EGM1023938910232121323432", "791098764902132", null);// 2、实物商品ICommodity commodityService2 = storeFactory.getCommodityService(2);commodityService2.sendCommodity("10001", "9820198721311", "1023000020112221113", new HashMap<String, String>() {{put("consigneeUserName", "谢飞机");put("consigneeUserPhone", "15200292123");put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");}});// 3、第三方兑换卡(爱奇艺)ICommodity commodityService3 = storeFactory.getCommodityService(3);commodityService3.sendCommodity("10001", "AQY1xjkUodl8LO975GdfrYUio", null, null);}@org.junit.Testpublic void testStoreFactory02() throws Exception {StoreFactory storeFactory = new StoreFactory();// 使用奖品类类型实例化ICommodity commodityService1 = storeFactory.getCommodityService(CouponCommodityServiceImpl.class);commodityService1.sendCommodity("10001", "EGM1023938910232121323432", "791098764902132", null);}
}
  • 测试结果
模拟发放优惠券一张:10001,EGM1023938910232121323432,791098764902132
10:47:39.306 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 请求参数[优惠券] => uId:10001 commodityId:EGM1023938910232121323432 bizId:791098764902132 extMap:null
10:47:39.351 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 测试结果[优惠券]:{"code":"0000","info":"发放成功"}
模拟发货实物商品一个:{"consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109","consigneeUserName":"谢飞机","consigneeUserPhone":"15200292123","orderId":"1023000020112221113","sku":"9820198721311","userName":"花花","userPhone":"15200101232"}
10:47:39.357 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 请求参数[实物商品] => uId:10001 commodityId:9820198721311 bizId:1023000020112221113 extMap:{"consigneeUserName":"谢飞机","consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109","consigneeUserPhone":"15200292123"}
10:47:39.358 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 测试结果[实物商品]:true
模拟发放爱奇艺会员卡一张:15200101232,null
10:47:39.359 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 请求参数[爱奇艺兑换卡] => uId:10001 commodityId:AQY1xjkUodl8LO975GdfrYUio bizId:null extMap:null
10:47:39.359 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 测试结果[爱奇艺兑换卡]:success模拟发放优惠券一张:10001,EGM1023938910232121323432,791098764902132
10:47:39.360 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 请求参数[优惠券] => uId:10001 commodityId:EGM1023938910232121323432 bizId:791098764902132 extMap:null
10:47:39.361 [main] INFO  c.l.s.i.CouponCommodityServiceImpl - 测试结果[优惠券]:{"code":"0000","info":"发放成功"}

4、工厂模式:总结

  • 工厂模式的优点

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

    • 有非常多的奖品类型,实现的子类会极速扩张

设计模式二:创建型-工厂模式相关推荐

  1. 设计模式之创建型——工厂模式(3种)

    →23种设计模式大纲 三种工厂模式 →23种设计模式大纲 定义 分类 1)简单工厂 UML类图 2)工厂方法 UML类图 3)抽象工厂 UML类图 总结 定义 将创建对象这一复杂的过程交由工厂控制,通 ...

  2. 设计模式二、抽象工厂模式

    设计模式part2 1.     抽象工厂模式 工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题, ...

  3. 设计模式 - 创建型 - 工厂模式

    2019独角兽企业重金招聘Python工程师标准>>> 介绍 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个产品类,工厂模式使其创建过程延迟到子类进行. 优点: 1.一个 ...

  4. Java设计模式之创建型-建造者模式 (Builder)

  5. java设计模式 (二) 创建模式

    java设计模式 (二) 创建型模式 单例模式 Singleton pattern 现实场景 双11, 小华收快递, 早上圆通快递叫他下楼收快递, 刚上来, 顺丰快递叫他下楼收快递,.然后没多久EMS ...

  6. 本文详细介绍Python 设计模式系列之二: 创建型 Simple Factory 模式(转载)

    源地址:http://doc.chinaunix.net/python/200703/202210.shtml 本文详细介绍Python 设计模式系列之二: 创建型 Simple Factory 模式 ...

  7. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  8. 设计模式(一)工厂模式Factory(创建型)

    设计模式一 工厂模式Factory 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题. ...

  9. 设计模式之创建型模式(工厂、原型、建造者)

    文章目录 创建型模式 2.1 工厂设计模式 2.1.1 简单工厂模式 2.1.2 工厂方法模式 2.1.3 抽象工厂 2.1.4 工厂模式总结 2.1.5 Spring中的工厂模式 2.1.6 工作中 ...

最新文章

  1. B站崩了上热搜,A站跟着躺枪!微信、支付宝:跟我们比起来这是小问题
  2. Docker容器的备份和还原
  3. Leetcode 127. 单词接龙 解题思路及C++实现
  4. java jni.h_java-如何使jni.h被找到?
  5. JSP页面中四种“返回按钮”的使用
  6. Python中使用class(),面向对象有什么优势
  7. linux 冒号命令,linux 的空命令:(冒号)
  8. OpenCV支持向量机SVM简介
  9. C语言进行网站开发之cgi
  10. 微信支付配置参数:支付授权目录、回调支付URL
  11. 网络编程知识预备(4) ——了解应用层的HTTP协议与HTTPS协议
  12. 人物角色群体攻击判定(一)
  13. 爬虫3 requests基础之 乱码编码问题
  14. HaLow技术提升车载Wi-Fi质量 促进车联网发展
  15. 用js实现分页功能以及利用xml实现分页功能——数据岛
  16. MeasureSpec详解
  17. SAP Transactions
  18. POJ 1877 Flooded!
  19. helm模板开发-流程控制、作用域、循环
  20. 【Windows】【VS】error C2220: 以下警告被视为错误

热门文章

  1. 沉睡者IT - 抖音中视频计划赚钱项目初级教程
  2. 三年打造AI芯片黑科技,IBM“狩猎女神之矛”将撬动企业混合云
  3. 睿联技术在创业板过会:收入依赖摄像机单机,计划募资11亿元
  4. redis排查读取超时、连接超时
  5. C++写文件时覆盖与否的问题
  6. 第二证券|下周解禁市值超980亿元,多家机构参与解禁股评级
  7. android 半透明色值_Android设置十六进制颜色不同透明度对应的值
  8. android自定义控件padding属性无效的解决
  9. 大学生前端,毕业面试知道这几点,offter拿到手软
  10. tosmana使用教程_20款最流行的免费定性数据分析工具