工厂模式(学习笔记 2021.6.11)

工厂模式(复习笔记 2021.6.11)

前言:

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

**意图:**定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

**主要解决:**主要解决接口选择的问题。

**何时使用:**我们明确地计划不同条件下创建不同实例时。

**如何解决:**让其子类实现工厂接口,返回的也是一个抽象的产品。

**关键代码:**创建过程在其子类执行。

应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

**缺点:**每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

**注意事项:**作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

工厂模式分为3种:

1: 简单工厂模式 (根据方法参数, 生产出不同的实例)

2: 方法工厂模式 (简单工厂的升级版, 为每一种实例构建不同的工厂, 对应工厂只负责生产对应实例)

3: 抽象工厂模式 (一个工厂, 不单单只能生产一种实例)

前提条件:

我们开了一家油漆工厂, 店内在售卖一种品牌油漆。

油漆(涂料) 是一个接口, 里面指定了涂料的保质期、品牌、颜色

public interface Coating {
    LocalDateTime shelfLife();
    String brand();
    String color();
}

假设根据用户需要的清单, 获取不同颜色的油漆, 普通的面向实现方式:

	@Test
    public void applicationTest() throws Exception {
        Coating coating = null;
        String color = "green";
        if ("red".equals(color)){
            coating = new RedCoating();
        }else if ("green".equals(color)){
            coating = new GreenCoating();
        }
        System.out.println("油漆品牌:"+coating.brand());
        System.out.println("油漆保质期:"+coating.shelfLife());
        System.out.println("油漆颜色:"+coating.color());
    }
//-----------
油漆品牌:嘉宝莉
油漆保质期:2021-06-12T00:00
油漆颜色:绿色

简单工厂:

下面利用简单工厂进行解耦, 不在由我们进行手动创建(new), 改为被动的从工厂获取实例对象

1.1 定义一个简单工厂

/**
 * @Author: ZhiHao
 * @Date: 2021/6/8 16:47
 * @Description: 简单工厂
 * @Versions 1.0
 **/
public class SimpleFactory {

    private String color;

    public SimpleFactory(String color) {
        this.color = color;
    }

    /** 
     * 判断逻辑从业务方, 移到了工厂
     *  
     * @return com.zhihao.interfaces.Coating 
     * @author: ZhiHao
     * @date: 2021/6/8 
     */
    public Coating createCoating() {
        Coating coating = null;
        if ("red".equals(color)) {
            coating = new RedCoating("嘉宝莉");
        } else if ("green".equals(color)) {
            coating = new GreenCoating("嘉宝莉");
        }
        return coating;
    }
}

1.2 业务方

改为被动的获取实例对象

@Test
    public void applicationTest() throws Exception {
        String color = "red";
        SimpleFactory simpleFactory = new SimpleFactory(color);
        Coating coating = simpleFactory.createEntity();
        System.out.println("油漆品牌:"+coating.brand());
        System.out.println("油漆保质期:"+coating.shelfLife());
        System.out.println("油漆颜色:"+coating.color());
    }
// 
油漆品牌:嘉宝莉
油漆保质期:2021-06-08T18:48:11.226
油漆颜色:红色

这就是最简单的工厂模式, 根据参数生产实例对象。

后面我们的工厂想扩展做大做强, 开分厂, 不单单只想生产一种嘉宝莉油漆了, 想扩展生产多2种不同品牌的油漆(三棵树, 嘉实多)。

如果这个时候用户想买5桶嘉宝莉与5桶三棵树, 还使用到简单工厂的话, 则需要增加一个创建涂料的参数了, 需要生产什么品牌与什么颜色的油漆了, 下面使用工厂方法进行职责划分更为清晰的模式进行解决!

工厂方法

工厂方法, 是简单工厂的一种升级, 使职责划分更为清晰, 什么工厂生产什么实例对象。 耦合更低

这种情况就需要抽象一个大家都遵守的工厂规则(类似规章制度, 只能生产油漆), 然后允许分厂做决定生产那个牌子。

1.1 定义一个抽象基类工厂

/**
 * @Author: ZhiHao
 * @Date: 2021/6/9 17:02
 * @Description: 需要大家都遵守规则的基础(总厂)
 * @Versions 1.0
 **/
public abstract class BaseFactory {

    /**
     * 生产油漆
     *
     * @return com.zhihao.interfaces.Coating
     * @author: ZhiHao
     * @date: 2021/6/9
     */
    public abstract Coating createCoating();
}

1.2 定义一个专门生产嘉宝莉工厂

/**
 * @Author: ZhiHao
 * @Date: 2021/6/9 17:09
 * @Description: 嘉宝莉工厂
 * @Versions 1.0
 **/
public class CarpolyFactory extends BaseFactory {

    private String color;

    public CarpolyFactory() {
    }

    public CarpolyFactory(String color) {
        this.color = color;
    }

    @Override
    public Coating createCoating() {
        Coating coating = null;
        if ("red".equals(color)) {
            coating = new RedCoating("嘉宝莉");
        } else if ("green".equals(color)) {
            coating = new GreenCoating("嘉宝莉");
        }
        return coating;
    }
}

1.3 定义一个专门生产三棵树工厂

/**
 * @Author: ZhiHao
 * @Date: 2021/6/9 17:09
 * @Description: 三棵树工厂
 * @Versions 1.0
 **/
public class ThreeTreesFactory extends BaseFactory {

    private String color;

    public ThreeTreesFactory() {
    }

    public ThreeTreesFactory(String color) {
        this.color = color;
    }

    @Override
    public Coating createCoating() {
        Coating coating = null;
        if ("red".equals(color)) {
            coating = new RedCoating("三棵树");
        } else if ("green".equals(color)) {
            coating = new GreenCoating("三棵树");
        }
        return coating;
    }
}

1.4 业务方

用户想买5桶嘉宝莉与5桶三棵树的绿色油漆

@Test
    public void applicationTest() throws Exception {
        String color = "red";
        // 先创建出2个工厂
        BaseFactory carpolyFactory = new CarpolyFactory(color);
        BaseFactory treesFactory = new ThreeTreesFactory(color);
        // 生产不同品牌
        Coating carpolyCoating = carpolyFactory.createCoating();
        Coating treesCoating = treesFactory.createCoating();
        System.out.println("油漆品牌:"+carpolyCoating.brand());
        System.out.println("油漆保质期:"+carpolyCoating.shelfLife());
        System.out.println("油漆颜色:"+carpolyCoating.color());
        System.out.println("油漆品牌:"+treesCoating.brand());
        System.out.println("油漆保质期:"+treesCoating.shelfLife());
        System.out.println("油漆颜色:"+treesCoating.color());
    }
//------------
油漆品牌:嘉宝莉
油漆保质期:2021-06-09T17:37:20.998
油漆颜色:红色
油漆品牌:三棵树
油漆保质期:2021-06-09T17:37:20.998
油漆颜色:红色

正式定义:

工厂方法模式定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个, 工厂方法让类把实例化推迟到子类。

如同在正式定义中所说的, 常常听到其他开发人员说: 工厂方法让子类决定要实例化的类是哪一个。希望不要理解错误, 所谓的“决定”, 并不是指模式允许子类本身在运行时做决定, 而是指在编写创建者类时, 不需要知道实际创建的产品是哪一个。选择了使用哪个子类,自然就决定了实际创建的产品是什么。

后面我们的工厂想进行扩展业务, 不仅仅出售生产油漆了, 想进行根据不同油漆捆绑销售油漆刷子、腻子、手套、等等相关产品。

抽象工厂

不仅仅可以生产一种产品, 可以生产一组产品, 允许客户创建对象的家族, 而无需指定他们的具体类

1.1 定义一个抽象基工厂接口

/**
 * @Author: ZhiHao
 * @Date: 2021/6/11 18:47
 * @Description: 抽象工厂接口
 * @Versions 1.0
 **/
public interface class AbstractBaseFactory {

     /**
     * 获取刷子附属产品
     *
     * @param name
     * @return com.zhihao.entity.AffiliatedProduct
     * @author: ZhiHao
     * @date: 2021/6/11
     */
    AffiliatedProduct getBrush(String name);

    /**
     * 获取手套附属产品
     *
     * @param name
     * @return com.zhihao.entity.AffiliatedProduct
     * @author: ZhiHao
     * @date: 2021/6/11
     */
    AffiliatedProduct getGlove(String name);
}
//----------AffiliatedProduct接口, Brush、Glove都实现了该接口-------
public interface AffiliatedProduct {String affiliatedProductName();}

1.2 定义一个专门生产嘉宝莉附属产品工厂

/**
 * @Author: ZhiHao
 * @Date: 2021/6/11 19:05
 * @Description: 嘉宝莉附属产品工厂
 * @Versions 1.0
 **/
public class CarpolyAffiliatedFactory implements AbstractBaseFactory {

    @Override
    public Brush getBrush(String name) {
        return new Brush("嘉宝莉"+name);
    }

    @Override
    public Glove getGlove(String name) {
        return new Glove("嘉宝莉"+name);
    }
}

1.3 定义一个专门生产三棵树附属产品工厂

/**
 * @Author: ZhiHao
 * @Date: 2021/6/11 19:05
 * @Description: 三棵树附属产品工厂
 * @Versions 1.0
 **/
public class ThreeTreesAffiliatedFactory implements AbstractBaseFactory {

    @Override
    public Brush getBrush(String name) {
        return new Brush("三棵树"+name);
    }

    @Override
    public Glove getGlove(String name) {
        return new Glove("三棵树"+name);
    }
}

1.4 改造Coating 油漆接口与其实现实体

public interface Coating {
    LocalDateTime shelfLife();
    String brand();
    String color();
    // 增加设置与返回附属产品
    AffiliatedProduct[] getAffiliatedProducts();
    AffiliatedProduct[] setAffiliatedProducts(AffiliatedProduct[] affiliatedProducts);
}
// 修改其2个油漆实体, 增加成员参数,  以下都是增加的参数, 其他参数省略不写
public class RedCoating implements Coating{

    private AffiliatedProduct[] affiliatedProducts;
    
    @Override
    public AffiliatedProduct[] getAffiliatedProducts() {
        return affiliatedProducts;
    }

    @Override
    public AffiliatedProduct[] setAffiliatedProducts(AffiliatedProduct[] affiliatedProducts) {
        return this.affiliatedProducts = affiliatedProducts;
    }
}
// GreenCoating 实体也和RedCoating 一模一样

1.5 改造工厂方法中createCoating方法

public class ThreeTreesFactory extends BaseFactory {
    private String color;
    private AbstractBaseFactory baseFactory;
    public ThreeTreesFactory(String color) {
        this.color = color;
        this.baseFactory = new ThreeTreesAffiliatedFactory();
    }

    @Override
    public Coating createCoating() {
        Coating coating = null;
        if ("red".equals(color)) {
            coating = new RedCoating("三棵树");
            coating.setAffiliatedProducts(new AffiliatedProduct[]{baseFactory.getBrush("红色油漆捆绑销售刷子")
                    ,baseFactory.getGlove("红色油漆捆绑销售手套")});
        } else if ("green".equals(color)) {
            coating = new GreenCoating("三棵树");
            coating.setAffiliatedProducts(new AffiliatedProduct[]{baseFactory.getBrush("绿色油漆捆绑销售刷子")
                    ,baseFactory.getGlove("绿色油漆捆绑销售手套")});
        }
        return coating;
    }
}
// 嘉宝莉工厂代码也是几乎一模一样

1.6 业务方

@Test
    public void applicationTest() throws Exception {
        String color = "red";
        // 先创建出2个工厂
        BaseFactory carpolyFactory = new CarpolyFactory(color);
        BaseFactory treesFactory = new ThreeTreesFactory(color);
        // 生产不同品牌
        Coating carpolyCoating = carpolyFactory.createCoating();
        Coating treesCoating = treesFactory.createCoating();
        System.out.println("油漆品牌:"+carpolyCoating.brand());
        System.out.println("油漆保质期:"+carpolyCoating.shelfLife());
        System.out.println("油漆颜色:"+carpolyCoating.color());
        Arrays.stream(carpolyCoating.getAffiliatedProducts()).forEach((affiliatedProduct)->
                System.out.println(affiliatedProduct.affiliatedProductName()));
        System.out.println("-----------------------------");
        System.out.println("油漆品牌:"+treesCoating.brand());
        System.out.println("油漆保质期:"+treesCoating.shelfLife());
        System.out.println("油漆颜色:"+treesCoating.color());
        Arrays.stream(treesCoating.getAffiliatedProducts()).forEach((affiliatedProduct)->
                System.out.println(affiliatedProduct.affiliatedProductName()));
    }
// ----
油漆品牌:嘉宝莉
油漆保质期:2021-06-11T19:47:23.895
油漆颜色:红色
嘉宝莉红色油漆捆绑销售刷子
嘉宝莉红色油漆捆绑销售手套
-----------------------------
油漆品牌:三棵树
油漆保质期:2021-06-11T19:47:23.897
油漆颜色:红色
三棵树红色油漆捆绑销售刷子
三棵树红色油漆捆绑销售手套

从上面可以看出, 我们的工厂油漆并不关心也并不知道附属产品是那个品牌, 达到了解耦,

后续在有附属产品, 则只需要构建一个抽象工厂生产一组附属产品

定义:

抽象工厂模式提供一个接口, 用于创建相关或依赖对象的家族(一组), 而不需要明确指定具体类。

抽象工厂允许客户使用抽象接口来创建一组的相关产品, 而不需要知道(或关心) 实际产出的具体产品是什么, 这样一来客户就从具体的产品中被解耦

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懵懵懂懂程序员

如果节省了你的时间, 请鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值