无中生有——抽象工厂模式

文章目录

  • 抽象工厂模式和工厂方法模式的关系
  • 抽象工厂模式
    • 适用场景
    • 优点
    • 缺点
    • 产品等级结构与产品族
    • Code
        • 业务场景
        • 模型分析
        • UML
        • 代码
  • 抽象工厂模式相关源码——兴趣阅读
    • jdk
    • 开源框架
  • 综述

抽象工厂模式和工厂方法模式的关系

  • 抽象工厂模式是工厂方法模式的一个进阶。进阶在哪里?进阶在产品和产品族的”族“。

  • 工厂方法模式旨在减少重复的创建对象代码,将创建对象这个任务交给具体的工厂。同时在上一篇工厂方法模式中,有谈到过它的弊端:对应每一种频繁创建的产品(对象)都需要创建一个工厂,那么每增加一个产品,就会至少增加2个类(一个产品,一个具体工厂)。导致类的数量增速很快。那么有什么方法可以解决这个问题?

  • 对产品进行分析:某些场景下,对于不同产品,他们会同属于一个产品族。举个例子:美的冰箱,格力冰箱,海尔冰箱。三种冰箱产品,他们是同一产品等级结构。通俗点就是属于同类产品:都是冰箱。再比如:美的空调,格力空调,海尔空调也是同一产品登记结构。那么美的冰箱,美的空调;格力冰箱,格力空调;海尔冰箱,海尔空调。这种都属于美的(或者格力,或者海尔)牌子的一系列产品。他们叫做同一产品族,而对于把同一产品族的创建放到同一个具体工厂里面,这种对工厂方法模式的扩展叫做抽象工厂模式。

  • 简单来讲:工厂方法模式是提供创建单一的产品对象。而抽象工厂模式是提供创建一系列产品族的产品对象。

抽象工厂模式

抽象工厂模式提供一个创建一系列相关或者相互依赖对象的接口

适用场景

  • 客户端不依赖于产品类实例如何被创建,实现等细节(同工厂方法模式)
  • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复代码(同工厂方法模式)
  • 提供一个产品族的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现

优点

  • 将一个系列的产品族统一到一起创建

缺点

  • 产品族中扩展新的产品困难,因为涉及到修改顶层接口,这个影响是巨大的!!!三个叹号应该懂我意思吧…

产品等级结构与产品族

  • 产品族:都是同一个工厂生产的。

例如,美的空调,美的电冰箱,他们就都是美的工厂生产的,就是同一产品族

  • 产品等级结构:是同一种类型的产品。

例如:美的空调,格力空调,都是空调,他们就是同一产品等级结构,都是空调

所以根据产品等级结构和产品族可以唯一确定一个产品。

Code

业务场景

  • 美的,海尔,格力三个品牌都有冰箱和空调。

模型分析

  • 抽象的冰箱,空调
  • 具体品牌的冰箱,空调
  • 抽象工厂(可以做成抽象类,也可以是接口)
  • 具体工厂

UML

  • IFactory是最顶层的工厂接口,定义了创建一个产品族的功能。
    • 抽象工厂模式,不好扩展的一点是因为,如果产品族中新增产品,那么就需要改动接口,改动接口,就会牵动所有的实现类,这就违反了开闭原则,且改动影响过大。
  • GreeFactory,MideaFactory,HaierFactory这三个是具体的厂商,他们都可以生产自己品牌的冰箱和空调
  • Firdge和其子类,以及AirConditioner和其子类都是同一产品等级下面不同牌子的产品。
    无中生有——抽象工厂模式_第1张图片

代码

  • 定义产品等级结构:冰箱和空调
/**
 * 冰箱
 */
public abstract class Fridge {

    // 品牌
    protected String brand;

    Fridge(String brand) {
        this.brand = brand;
    }


    protected abstract void show();
}
/**
 * 空调
 */
public abstract class AirConditioner {

    // 品牌
    protected String brand;

    AirConditioner(String brand) {
        this.brand = brand;
    }


    protected abstract void show();
}
  • 定义不同品牌的产品实例:分别是美的,格力,海尔
/**
 * 美的冰箱
 * @author zhongyuan.zhao
 * @date 2020-05-23 15:39
 */
public class MideaFridge extends Fridge {

    public MideaFridge(){
        super("美的冰箱");
    }

    @Override
    protected void show() {
        System.out.println( this.brand);
    }
}
/**
 * 美的空调
 * @author zhongyuan.zhao
 * @date 2020-05-23 21:36
 */
public class MideaAirConditioner extends AirConditioner{

    MideaAirConditioner() {
        super("美的空调");
    }

    @Override
    protected void show() {
        System.out.println(this.brand);
    }
}
/**
 * 格力冰箱
 */
public class GreeFridge extends Fridge {

    public GreeFridge(){
        super("格力冰箱");
    }

    @Override
    protected void show() {
        System.out.println(this.brand);
    }
}
/**
 * 格力空调
 */
public class GreeAirConditioner extends AirConditioner {

    GreeAirConditioner() {
        super("格力空调");
    }

    @Override
    protected void show() {
        System.out.println(this.brand);
    }
}
/**
 * 海尔冰箱
 */
public class HaierFridge extends Fridge {

    public HaierFridge(){
        super("海尔冰箱");
    }

    @Override
    protected void show() {
        System.out.println(this.brand);
    }
}
/**
 * 海尔空调
 */
public class HaierAirConditioner extends AirConditioner{

    HaierAirConditioner() {
        super("海尔空调");
    }

    @Override
    protected void show() {
        System.out.println(this.brand);
    }
}
  • 定义产品族抽象创建工厂
/**
 * 产品族工厂
 */
public interface IFactory {

    /**
     * 创建冰箱
     *
     * @return
     */
    Fridge createFridge();

    /**
     * 创建空调
     * @return
     */
    AirConditioner createAirConditioner();

}
  • 定义不同品牌产品的具体工厂:美的,格力,海尔
/**
 * 美的工厂
 */
public class MideaFactory implements IFactory {

    @Override
    public Fridge createFridge() {
        return new MideaFridge();
    }

    @Override
    public AirConditioner createAirConditioner() {
        return new MideaAirConditioner();
    }
}
/**
 * 海尔工厂
 */
public class HaierFactory implements IFactory {

    @Override
    public Fridge createFridge() {
        return new HaierFridge();
    }

    @Override
    public AirConditioner createAirConditioner() {
        return new HaierAirConditioner();
    }
}
/**
 * 格力工厂
 */
public class GreeFactory implements IFactory {

    @Override
    public Fridge createFridge() {
        return new GreeFridge();
    }

    @Override
    public AirConditioner createAirConditioner() {
        return new GreeAirConditioner();
    }
}
  • 客户端测试类
/**
 * 客户端
 *
 * @author zhongyuan.zhao
 * @date 2020-05-23 15:49
 */
public class MainTest {


    public static void main(String[] args) {
        // 创建格力工厂
        IFactory factory = new GreeFactory();
        // 制造出的就是格力冰箱和空调
        Fridge fridge = factory.createFridge();
        AirConditioner airConditioner = factory.createAirConditioner();
        if (Objects.isNull(fridge) || Objects.isNull(airConditioner)){
            return;
        }
        // 预计打印结果应该是格力冰箱和格力空调
        fridge.show();
        airConditioner.show();
    }
}
  • 运行结果
    无中生有——抽象工厂模式_第2张图片

抽象工厂模式相关源码——兴趣阅读

jdk

  • java.sql.Connection java操作数据库连接的功能定义接口
    • 在这个接口中定义的返回,比如Statement,PreparedStatement等其实都是一个产品族。是抽象工厂模式的一种实现。Statement,PreparedStatement本身也是一个抽象工厂模式的工厂接口。不同的数据库厂商(mysql,oracle等等)实现自己的产品对象(Statement,PreparedStatement)。

开源框架

  • mybatis
    • SqlSessionFactory 通过SqlSessionFactory 获取的都是属于同一的产品族。其中SqlSession就是mybatis工作的核心。

综述

  • 抽象工厂模式和工厂方法模式之间的区别就是产品族和产品的区别。
  • 抽象工厂模式的优点:将同一产品族的创建统一起来。
  • 抽象工厂模式的缺点:扩展产品等级结构(比如格力某天要生产电脑)的时候,影响范围会很广,不易扩展。
  • 适用场景:有产品族的频繁创建的时候。

再次细品工厂模式(工厂方法模式,抽象工厂模式),本质上,就是让我们在代码中不要有太多的重复的创建相同对象的操作,这种操作会让我们的代码中有大量的重复代码(这是一种代码坏味道),如果有这种相同对象频繁创建的情况,可以考虑使用工厂模式进行优化。

一句话总结:工厂模式就是防止代码中有太多重复创建相同对象的代码!

你可能感兴趣的:(《三十六计》)