一、简单工厂模式定义
简单工厂模式不是一种设计模式,反而比较像一种编程习惯。
简单工厂模式又叫静态工厂方法模式(static Factory Method pattern),它使用静态
方法接收接收不同的参数返回不同的实例对象。
二、实现方式
定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例有共同的父类或接口
三、适用场景
1、被创建的对象较少
2、客户端不关心对象创建的过程
四、简单工厂结构
1、简单工厂包含如下角色:
1)抽象产品:定义了产品的规范,描述了产品的主要特性和功能
2)具体产品:实现或继承抽象产品的子类
3)产品工厂:提供了创建产品的方法,调用者通过该方法来获取产品
五、简单工厂模式使用示例
1、需求
现有一个需求,模拟抽奖活动的奖品发送流程,现有3种奖品:打折卷、优酷会员和
小礼品,需要把这3种奖品发到中奖人手中。
2、不使用设计模式方式实现
对于上边的需求,如果是一个小白来实现,不考虑代码后期的扩展性,可能会这样实现:
1)分别为每种奖品和获奖人创建一个实体类,如下所示:
2)为每种奖品的发放创建一个奖品发放业务类
3)创建客户端类,在客户端类通过奖品类型来区分发放那种奖品,
2.1)UML类图如下:
2.2)代码如下:
/*******************************************************
* 小礼品信息对应实体类
*******************************************************/
@Data
public class SmallGiftInfo {
/**
* 用户名称
*/
private String userName;
/**
* 手机号
*/
private String phone;
/**
* 礼品标识
*/
private String orderId;
/**
* 地址
*/
private String address;
}
/*******************************************************
* 获奖信息实体类
* 不使用设计模式,原始方式实现
*******************************************************/
@Data
public class AwardInfo {
/**
* 用户id
*/
private String uid;
/**
* 奖品类型,1-打折卷,2-优酷会员,3-小礼品
*/
private Integer awardTypes;
/**
* 奖品编号
*/
private String awardNumber;
/**
* 额外信息
*/
private Map<String,String> extMap;
}
/*******************************************************
*
* 打折卷操作响应结果类
*
*******************************************************/
@Data
public class ResponseResult {
private String status;
private String message;
public Object data;
public ResponseResult(String status, String message) {
this(status,message,null);
}
public ResponseResult(String status, String message,Object data) {
this.status = status;
this.message = message;
this.data = data;
}
}
发送奖品业务逻辑代码
/*******************************************************
*
* 打折卷service
*******************************************************/
public class DiscountService {
public ResponseResult sendDiscount(String uid,String awardNumber){
System.out.println("向用户发送一张打折卷:"+uid+" , "+awardNumber);
return new ResponseResult("200","发送打折卷成功 ");
}
}
/*******************************************************
* 小礼品发放业务逻辑
*******************************************************/
public class SmallGifService {
public Boolean giveSmallGif(SmallGiftInfo smallGiftInfo){
System.out.println("小礼品已经发送,获奖用户请注意查收: "+ JSON.toJSON(smallGiftInfo));
return true;
}
}
/*******************************************************
* 优酷会员发放业务逻辑
*******************************************************/
public class YouKuMemberService {
public void openMember(String bingPhone,String awardNumber){
System.out.println("发送优酷会员卷:"+bingPhone+", "+awardNumber);
}
}
/*******************************************************
*
* 发放奖品操作
*
*******************************************************/
public class DeliverController {
public void awardToUser(AwardInfo awardInfo){
/**
* 根据奖品类型发送奖品
* 奖品类型,1-打折卷,2-优酷会员,3-小礼品
*/
if(awardInfo.getAwardTypes() == 1){
DiscountService discountService = new DiscountService();
discountService.sendDiscount(awardInfo.getUid(),awardInfo.getAwardNumber());
System.out.println("打折卷发送成功");
}else if(awardInfo.getAwardTypes() == 2){
String phone = awardInfo.getExtMap().get("phone");
YouKuMemberService youku = new YouKuMemberService();
youku.openMember(phone,awardInfo.getAwardNumber());
System.out.println("优酷会员发送成功");
}else if(awardInfo.getAwardTypes() == 3){
String username = awardInfo.getExtMap().get("username");
String phone = awardInfo.getExtMap().get("phone");
String address = awardInfo.getExtMap().get("address");
SmallGiftInfo info = new SmallGiftInfo();
info.setOrderId(UUID.randomUUID().toString());
info.setUserName(username);
info.setPhone(phone);
info.setAddress(address);
SmallGifService service = new SmallGifService();
//发送小礼品
Boolean bool = service.giveSmallGif(info);
if(bool){
System.out.println("小礼品发送成功");
}
}
}
}
3、使用简单工厂模式重构上边代码
3.1)简单工厂模式下类图如下:
3.2)代码如下:
/*******************************************************
* 产品工厂
* 根据礼品类型不同,返回对应的 IFreeGoods 实现类
*******************************************************/
public class FreeGoodsFactory {
public static IFreeGoods getInstance(Integer type){
if(type == 1){
return new DiscountFreeGoods();
}else if(type == 2){
return new YouKuMemberFreeGoods();
}else if(type == 3){
return new SmallGifFreeGoods();
}
return null;
}
}
/**
* 奖品发送接口
*/
public interface IFreeGoods {
ResponseResult sendGoods(AwardInfo award);
}
/*******************************************************
*
* 发放打折卷
*
*******************************************************/
public class DiscountFreeGoods implements IFreeGoods {
@Override
public ResponseResult sendGoods(AwardInfo award) {
String uid = award.getUid();
String awardNumber = award.getAwardNumber();
return new ResponseResult("200","给用户 "+uid+"发送打折卷成功 "+awardNumber);
}
}
/*******************************************************
*
* 发送小礼品
*
*******************************************************/
public class SmallGifFreeGoods implements IFreeGoods {
@Override
public ResponseResult sendGoods(AwardInfo award) {
SmallGiftInfo smallGiftInfo = new SmallGiftInfo();
smallGiftInfo.setUserName(award.getExtMap().get("username"));
smallGiftInfo.setPhone(award.getExtMap().get("phone"));
smallGiftInfo.setAddress(award.getExtMap().get("address"));
smallGiftInfo.setOrderId(UUID.randomUUID().toString());
System.out.println("小礼品发送成功,请注意查收!");
return new ResponseResult("200","小礼品发送成功",smallGiftInfo);
}
}
/*******************************************************
*
* 发送优酷会员
*
*******************************************************/
public class YouKuMemberFreeGoods implements IFreeGoods {
@Override
public ResponseResult sendGoods(AwardInfo award) {
String phone = award.getExtMap().get("phone");
System.out.println("发放优酷会员成功。绑定手机号:"+phone);
return new ResponseResult("200","发放优酷会员成功。绑定手机号:"+phone);
}
}
/*******************************************************
*
* 客户端
* 发放奖品
*
*******************************************************/
public class DeliverController {
public ResponseResult awardToUser(AwardInfo awardInfo){
IFreeGoods freeGoods = FreeGoodsFactory.getInstance(awardInfo.getAwardTypes());
return freeGoods.sendGoods(awardInfo);
}
}
六、简单工厂模式优缺点
5.1)简单工厂模式优点
1)封装了创建对象的过程,可以通过参数直接获取对象,把对象的创建与业务
逻辑分开,避免了后边可能修改业务代码的问题。
2)提高了代码的可扩展性,如果要增加新产品,则只需要修改工厂类,不需要
修改源代码,降低了客户端修改代码的可能性,更容易扩展。
5.2)简单工厂模式缺点
1)在增加新产品的时候还需要修改代码,违背了开闭原则;
注意:
“开闭原则”:对扩展开放,对修改关闭,并不是说旧代码一点也不能
修改;在实际开发中,很多时候业务扩展对旧代码完全不修改是很难
办到的;如果修改的代码量很少的话,还是可以接受的。