设计模式之工厂方法模式

2024-04-10 1169阅读

一、介绍

        工厂方法模式 Factory Method Pattern,属于创建型模式。

        定义一个用于创建对象的接口,让子类决定实例化哪个产品类型对象。

         工厂方法是一个产品类的实例化过程 延迟到其工厂的子类。

       

二、工厂方法模式原理

        工厂方法模式的目的很简单,就是封装对象创建的过程,提升创建对象方法的

        可复用性,只要是创建对象的地方都可以用工厂方法模式替代创建对象的过程。

        工厂方法模式的主要角色:

               1)抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂

                                       方法来创建产品

               2)具体工厂:主要实现抽象工厂中的抽象方法,完成具体产品的创建。

               3)抽象产品:定义了产品的规范,描述产品的主要特性和功能。

               4)具体产品:实现了抽象产品所定义的接口,由具体工厂来创建具体产品对象,

                                       具体产品同具体工厂之间一一对应,工厂方法就没必要传参数了。

          工厂方法UML图:

          设计模式之工厂方法模式

三、工厂方法模式优缺点

        1、有点

                 1)用户只需要知道知道具体工厂,就可以获取想要的产品,不需要关注

                       产品的创建过程。

                 2) 在系统增加新产品的时候,只需要添加具体产品类及对应的具体工厂,

                       不需要对原工厂进行修改,满足了“开闭原则”

         2、缺点

                 1)每增加一个产品,就需要新增具体的产品类及具体的工厂方法,这样

                      会增加系统的复杂度

四、工厂方法模式使用场景

        例如:使用工厂方法模式对“简单工厂模式” 中的代码进行重构

        3.1)使用工厂方法模式实现“模拟奖品发放”的UML图如下:

                设计模式之工厂方法模式

       3.2)代码如下:

            产品代码  

/**
 * 奖品发送接口
 */
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 interface FreeGoodsFactory {
    public IFreeGoods getInstance();
}
/*******************************************************
 * 具体工厂
 * 用于创建 发放打折卷 对象
 *******************************************************/
public class DiscountFreeGoodsFactory implements FreeGoodsFactory{
    @Override
    public IFreeGoods getInstance() {
        return new DiscountFreeGoods();
    }
}
/*******************************************************
 *
 * 具体工厂,用于创建 发放小礼品对象
 *******************************************************/
public class SmallGifFreeGoodsFactory implements FreeGoodsFactory{
    @Override
    public IFreeGoods getInstance() {
        return new SmallGifFreeGoods();
    }
}
/*******************************************************
 * 具体工厂,用于创建 优酷会员奖品对象
 *******************************************************/
public class YouKuMemberFreeGoodsFactory implements FreeGoodsFactory{
    @Override
    public IFreeGoods getInstance() {
        return new YouKuMemberFreeGoods();
    }
}

客户端代码 

/*******************************************************
 * Client
 * 
 *******************************************************/
public class DeliverController {
    
    public ResponseResult awardToUser(AwardInfo awardInfo){
        FreeGoodsFactory factory = null;
        if(awardInfo.getAwardTypes() == 1){
            factory = new DiscountFreeGoodsFactory();
        }else if(awardInfo.getAwardTypes() == 2){
            factory = new YouKuMemberFreeGoodsFactory();
        }else if(awardInfo.getAwardTypes() == 3){
            factory = new SmallGifFreeGoodsFactory();
        }
        IFreeGoods freeGoods = factory.getInstance();
        ResponseResult responseResult = freeGoods.sendGoods(awardInfo);
        return responseResult;
    }
}

五、对工厂模式进一步优化

       观察上边工厂模式重构的发送奖品代码发现,当有新的产品增加时,还是需要修改业务代码

       的,这就破坏了“开闭原则”;针对这种情况我们可以创建一个工厂缓冲池的方式来优化

       工厂方法,代码如下:

/*******************************************************
 *
 *  优化工厂方法:
 *  创建工厂缓冲池,当产品增加时,只需要向工厂池中增加新的工厂实例,
 *  不需要修改代码
 *******************************************************/
public class FreeGoodsFactoryCollection {
    private static final Map FACTORY_POOL = new HashMap();
    //
    static {
        FACTORY_POOL.put(1,new DiscountFreeGoodsFactory());
        FACTORY_POOL.put(2,new YouKuMemberFreeGoodsFactory());
        FACTORY_POOL.put(1,new SmallGifFreeGoodsFactory());
    }
    /**
     * 客户端获取工厂的方法
     * 
     * @param type
     * @return
     */
    public static FreeGoodsFactory getFactory(Integer type){
        return FACTORY_POOL.get(type);
    }
}

客户端调用如下:

public class DeliverController {
    public ResponseResult awardToUser(AwardInfo awardInfo){
        FreeGoodsFactory factory = FreeGoodsFactoryCollection.getFactory(awardInfo.getAwardTypes());
        IFreeGoods freeGoods = factory.getInstance();
        ResponseResult responseResult = freeGoods.sendGoods(awardInfo);
        return responseResult;
    }
}
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]