工厂方法模式

  • 一、定义
  • 二、示例:
    • 传统硬编码方式(都在一个类里面实现,多重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;                   // 商品SKUprivate String orderId;               // 订单IDprivate 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;                 // 用户唯一IDprivate Integer awardType;          // 奖品类型(可以用枚举定义);1优惠券、2实物商品、3第三方兑换卡(爱奇艺)private String awardNumber;         // 奖品编号;sku、couponNumber、cardIdprivate 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<String, String> 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();@Overridepublic 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();@Overridepublic 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();@Overridepublic 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 {@Testpublic 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);}@Testpublic 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);}
}

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

JAVA【设计模式】工厂方法模式相关推荐

  1. JAVA设计模式 - 工厂方法模式

    工厂方法模式(Factory Pattern) 是一种创建型设计模式 , 它是Java中最常用的设计模式之一 . 1 . 工厂方法模式的定义 定义一个创建对象的接口 , 让子类决定实例化哪一个类 . ...

  2. Java设计模式--工厂方法模式

    工厂方法模式 1.工厂方法模式的概述 1.1工厂模式是简单工厂模式的延伸,符合开闭原则的基础上,还可以在增加新的具体产品对象时不需要对已有系统做任何修改. 1.2工厂方法模式:定义一个用于创建对象的接 ...

  3. 《转》java设计模式--工厂方法模式(Factory Method)

    本文转自:http://www.cnblogs.com/archimedes/p/java-factory-method-pattern.html 工厂方法模式(别名:虚拟构造) 定义一个用于创建对象 ...

  4. Java设计模式-工厂方法模式和抽象工厂模式

    工厂方法模式定义: 即定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类)."一对一"的关系 1,一抽象工厂类派生出多个具体工厂类: 2, ...

  5. Java设计模式—工厂方法模式抽象工厂模式

    工厂方法模式与抽象工厂模式都是设计模式中重要而且常见的模式.       工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 通用类图如下: 在 ...

  6. Java设计模式-工厂方法模式的使用和介绍

    一.工厂方法模式简介 1.定义 工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorph ...

  7. java设计模式---工厂方法模式

    简单工厂模式的应用就是用来创建一个对象,简单工厂模式是将所有对象的初始化集于一个具体的工厂类来实现,这个工厂类负责所有产品的创建,但是这种创建只能创建单一的产品,如简单工厂模式里的ChickenFac ...

  8. java设计模式——工厂方法模式

    工厂方法模式:为工厂类定义了接口,使用多态来削弱工厂类的职责. * 将简单工厂创建对象的职责分担到子工厂类中,子工厂相互独立,互相不受影响. * 工厂方法模式也有他的局限性,当面对有复杂的树形结构的产 ...

  9. Java——设计模式(工厂方法模式)

    * A:工厂方法模式概述* 工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现.* 简单来说:先定义一个工厂,工厂里面有些方法,这些方法就是用来创建动物的,然 ...

  10. 我的Java设计模式-工厂方法模式

    转载 https://zhuanlan.zhihu.com/p/29549253 转载于:https://www.cnblogs.com/thiaoqueen/p/8298328.html

最新文章

  1. Shift Dot_JAVA
  2. java restful接口测试_详解SpringBoot restful api的单元测试
  3. php变量前下滑_PHP变量
  4. JAVAEWEB实现文件的上传案例
  5. matlab 信道模拟 差错概率,移动信道差错序列的分布概率模拟法及门限电平的讨论...
  6. 再学 GDI+[65]: 路径画刷(5) - SetGammaCorrection
  7. 《数学建模与数学实验》第5版 作图 习题2.6
  8. 华为5.0以上设备(亲测有效)激活xposed框架的流程
  9. 2021-2027全球与中国零售空间规划软件市场现状及未来发展趋势
  10. sam格式的结构和意义_SAM文件是什么
  11. 为什么越来越多的人选择了企业微信
  12. C/C++ 16bit转8bit
  13. 从程序员到项目经理(25):对绩效考核的吐槽
  14. 橙子钱包app是谁做的?
  15. TNF 又见 《Cell》
  16. Android6.0以上应用在长时间在后台,因为内存不足导致系统回收内存,当再次启动应用出现Fragment重叠或者空白、异常解决方案(提供模拟内存不足导致系统回收内存的方案)。
  17. 【JAVA】学习java 基础知识
  18. 分数换算小数补0法_一年级数学0基础的全过来,最全知识点及基本方法,包你数学不补课都90+...
  19. 鸿蒙手机摄影,鸿蒙系统正式亮相 华为:手机随时可以使用
  20. tc网络流控详解及常用队列

热门文章

  1. 勃林格殷格翰在华开启马业务,中国首个进口马专用药物骏卫保获批
  2. 手机居然可以变成电脑的无线麦克风?快来瞧瞧
  3. android SoundPool 音效播放
  4. 新用户报到,以及门电路相关手游推荐
  5. mavennexus环境搭建
  6. 不可重复读和幻读有什么区别?
  7. 考初级计算机证需要考什么,计算机初级证书要考哪些内容
  8. 2019-8-24 小米商城商品展示界面
  9. 关于技嘉雷电扩展卡SSDT驱动教程
  10. Springboot集成百度地图实现定位打卡功能