当前位置: 首页 > article >正文

设计模式--抽象工厂模式【创建型模式】

设计模式的分类

我们都知道有 23 种设计模式,这 23 种设计模式可分为如下三类:

  • 创建型模式(5 种):单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
  • 结构型模式(7 种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式(11 种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

在这里插入图片描述

设计模式系列文章传送门

设计模式的 7 大原则

设计模式–单例模式【创建型模式】

设计模式–工厂方法模式【创建型模式】

什么是抽象工厂模式?

抽象工厂模式是一种创建型模式,该模式提供了一个超级工厂(抽象工厂),其他工厂来是实现这个工厂接口,同时还有一个工厂创建类,通过传入不同的参数,来创建不同的工厂,抽象工厂 模式是对工厂模式的扩展,工厂模式只是某类产品的工厂,而抽象工厂则是多类产品的工厂,可以理解为一类产品(产品族)的工厂,而抽象工厂就是工厂的工厂,是一个超级工厂。

产品族

产品族是指一类具有共同特征、相互关联的产品组合,它指的是一系列的产品,这些产品可能具有不同的规格、配置或者功能,抽象工厂模式就是对一系列产品就组成一个产品族,(工厂方法提供的一系列产品组成一个产品)。比如同样是车,我们会区分家用小汽车和货运重卡,而家用小汽车又有小米、小鹏等品牌,而活用重卡又有解放、东风等品牌,而他们又都属于车这个产品族。

抽象工厂五要素

  • 抽象工厂:定义一个接口,它声明了一组创建相关产品对象的方法,这些方法的返回值都是一个抽象产品。
  • 具体工厂:实现了抽象工厂中创建对象的方法,创建出具体的产品对象。
  • 抽象产品:定义了一个接口,声明了产品的一些方法。
  • 具体产品:定义了抽象产品下的某个具体产品,实现了抽象产品接口中的方法。
  • 工厂创造器:定义了一个静态方法,根据传入的参数类型,创建一个具体的工厂类。

案例分享

我们使用车产品模拟一个产品大类(产品族),车产品中又有家用小汽车和货用重卡,而家用小汽车又有小米、小鹏等品牌,而活用重卡又有解放、东风等品牌,我们使用这个案例来演示抽象工厂模式。

小汽车接口(抽象产品)

定义小汽车接口,包含汽车创始人、型号、品牌、颜色等方法,代码如下:

public interface CompactCar {

    //汽车品牌
    String getBrand();

    //汽车创始人
    String getFounder();

    //汽车型号
    String getModel();

    //汽车颜色
    String getColor();

}

定义小米汽车(具体产品)

家用小汽车有诸多品牌,我们定义一个小米汽车,代码如下:

public class XiaoMiCar implements CompactCar {
    @Override
    public String getBrand() {
        return "小米";
    }

    @Override
    public String getFounder() {
        return "雷布斯";
    }

    @Override
    public String getModel() {
        return "su7";
    }

    @Override
    public String getColor() {
        return "蓝色";
    }
}

定义小鹏汽车(具体产品)

我们再定义一个家用汽车品牌中的小鹏汽车,代码如下:

public class XiaoPengCar implements CompactCar {
    @Override
    public String getBrand() {
        return "小鹏";
    }

    @Override
    public String getFounder() {
        return "何小鹏";
    }

    @Override
    public String getModel() {
        return "小鹏P7";
    }

    @Override
    public String getColor() {
        return "炫酷黑";
    }
}

货用重卡接口(抽象产品)

货用重卡也是车中的一类,货用重卡接口包含汽车品牌、载重、颜色等方法,代码如下:

public interface BigTruck {

    //汽车品牌
    String getBrand();

    //汽车载重
    String getLoad();

    //汽车颜色
    String getColor();
    
}

定义东风重卡汽车(具体产品)

货用重卡汽车有诸多品牌,我们定义一个东风重卡汽车,代码如下:

public class DongFengCar implements BigTruck{
    @Override
    public String getBrand() {
        return "东风重卡";
    }

    @Override
    public String getLoad() {
        return "60吨";
    }

    @Override
    public String getColor() {
        return "红色";
    }
}

定义解放重卡汽车(具体产品)

解放重卡汽车有诸多品牌,我们定义一个解放重卡汽车,代码如下:

public class JieFangCar implements BigTruck{
    @Override
    public String getBrand() {
        return "一汽解放重卡";
    }

    @Override
    public String getLoad() {
        return "50吨";
    }

    @Override
    public String getColor() {
        return "橙色";
    }
}

定义抽象车工厂接口(抽象工厂)

抽象车工厂接口中声明了两个方法,分别是创建家用小汽车和货用重卡。

public interface AbstractCarFactory {

    //生产小汽车接口
    CompactCar createCompactCar(String carType);

    //生产大货车接口
    BigTruck createBigTruck(String carType);

}

定义小汽车工厂接口(具体工厂)

小汽车工厂实现了抽象车工厂接口,代码如下:

public class CompactCarFactory implements AbstractCarFactory {

    //创建小米汽车
    @Override
    public CompactCar createCompactCar(String carType) {
        if("xiaomi".equals(carType)){
            return new XiaoMiCar();
        }else  if("xiaopeng".equals(carType)){
            return new XiaoPengCar();
        }
        return null;
    }

    @Override
    public BigTruck createBigTruck(String carType) {
        return null;
    }
}

可以看到小汽车工厂也实现了货用重卡的方法,这就是抽象工厂方法的弊端,小汽车工厂根本用不到货用重卡的方法,但因为实现了抽象车工厂接口,就必须重写货用重卡的方法。

定义货用重卡工厂接口(具体工厂)

货用重卡工厂实现了抽象车工厂接口,代码如下:

public class BigTruckFactory implements AbstractCarFactory{
    @Override
    public CompactCar createCompactCar(String carType) {
        return null;
    }

    @Override
    public BigTruck createBigTruck(String carType) {
        if("dongfeng".equals(carType)){
            return new DongFengCar();
        }else if("jiefang".equals(carType)){
            return new JieFangCar();
        }
        return null;
    }
}

定义工厂创造器

定义工厂创造器可以根据我们传入的工厂类型帮我们生产具体的工厂,代码如下:

public class FactoryCreator {

    public static AbstractCarFactory createFactory(String factoryType) {
        if ("compact".equals(factoryType)) {
            return new CompactCarFactory();
        } else if ("bigtruck".equals(factoryType)) {
            return new BigTruckFactory();
        }
        return null;
    }
}

看起来工厂创造器其实是可有可无的,非必须得,看个人喜好。

测试验证

测试抽象工厂模式代码如下:

public class CarClient {

    public static void main(String[] args) {
        AbstractCarFactory compact = FactoryCreator.createFactory("compact");
        CompactCar xiaomi = compact.createCompactCar("xiaomi");
        System.out.println(xiaomi.toString());
        CompactCar xiaopeng = compact.createCompactCar("xiaopeng");
        System.out.println(xiaopeng.toString());
        AbstractCarFactory bigtruck = FactoryCreator.createFactory("bigtruck");
        BigTruck dongfeng = bigtruck.createBigTruck("dongfeng");
        System.out.println(dongfeng.toString());
        BigTruck jiefang = bigtruck.createBigTruck("jiefang");
        System.out.println(jiefang.toString());

    }

}

测试执行结果如下:

com.xxx.xxx.xxx.factory.abstractfactory.XiaoMiCar@6d5380c2
com.xxx.xxx.xxx.factory.abstractfactory.XiaoPengCar@45ff54e6
com.xxx.xxx.xxx.factory.abstractfactory.DongFengCar@2328c243
com.xxx.xxx.xxx.factory.abstractfactory.JieFangCar@bebdb06

工厂模式优缺点

优点:

  • 客户端独立于具体的实现类,将产品的使用和创建分开,客户端使用工厂来穿件产品,无需关心产品的实现,隐藏了产品细节同时也有一定的解耦。
  • 增加产品容易,比如我们现在有小米和小鹏家用汽车,再增加一个蔚来汽车是很容易的。

缺点:

  • 增加新品类困难,如果想要新增一个新的品类,需要修改抽象接口代码已经下游所有代码,比如我们新增一个火车类(这里区别于新在一个品类的一个产品)。
  • 引入了抽象层,增加了系统的抽象性和理解难度,增加了代码复杂度,对于不熟悉该模式的开发人员来说,理解起来可能会有一些困难。

应用场景

  • 需要对一个产品族下的不同产品类型提供同意的访问接口,不关心某个产品的具体实现的场景。
  • 需要运行中动态的选择某种产品的场景。

总结:本篇结合理论和案例分享了抽象工厂设计模式,相比工厂方法模式,抽象工厂方法模式理解起来会更困难一点,希望不熟悉抽象工厂模式的朋友们可以静下心来分析,相信会有所帮助。

如有不正确的地方欢迎各位指出纠正。


http://www.kler.cn/a/450101.html

相关文章:

  • Datawhale AI 冬令营学习笔记-零编程基础制作井字棋小游戏
  • 【魅力golang】之-通道
  • V900新功能-电脑不在旁边,通过手机给PLC远程调试网关配置WIFI联网
  • 蓝桥杯物联网开发板硬件组成
  • kotlin中泛型中in和out的区别
  • 3D架构图软件 iCraft Editor 正式发布 @icraftplayer-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
  • 利用Spring Cloud Gateway Predicate优化微服务路由策略
  • 【wordpress】建立数据库连接时出错,您看到此页面,则表示您在 wp-config.php 文件中定义的用户名和密码信息不正确,或是……
  • QT——day1
  • 畅捷通-条件竞争
  • 前端开发 之 12个鼠标交互特效上【附完整源码】
  • 120页PPT讲解ChatGPT如何与财务数字化转型的业财融合
  • Scala_【2】变量和数据类型
  • 批量生成二维码,助力数字化管理-Excel易用宝
  • Debezium日常分享系列之:Debezium 3.0.5.Final发布
  • 腾讯云云开发 Copilot具有以下优势
  • 外连接转AntiJoin的应用场景与限制条件 | OceanBase SQL 查询改写系列
  • 微服务——数据管理与一致性
  • [前端]mac安装nvm(node.js)多版本管理
  • sqoop,flume草稿
  • animatediff 模型网盘分享
  • 专业的内外网数据交换方案 可解决安全、效率、便捷3大问题
  • 单例Bean
  • 数据迁移工具,用这8种!
  • 探索Moticon智能传感器鞋垫OpenGo的功能与优势
  • AI领域年度精彩报告┆国家优青马超教授:自动驾驶多模态场景理解与生成