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

设计模式-创建型模式-(工厂、简单工厂、抽象工厂)

一、简单工厂模式

上代码

public class FoodFactory {public static Food makeFood(String name) {if (name.equals("noodle")) {Food noodle = new LanZhouNoodle();noodle.addSpicy("more");return noodle;} else if (name.equals("chicken")) {Food chicken = new HuangMenChicken();chicken.addCondiment("potato");return chicken;} else {return null;}}
}

二、工厂模式

简单工厂模式很简单,如果它能满足我们的需要,我觉得就不要折腾了。之所以需要引入工厂模式,是因为我们往往需要使用两个或两个以上的工厂

public interface FoodFactory {Food makeFood(String name);
}
public class ChineseFoodFactory implements FoodFactory {@Overridepublic Food makeFood(String name) {if (name.equals("A")) {return new ChineseFoodA();} else if (name.equals("B")) {return new ChineseFoodB();} else {return null;}}
}
public class AmericanFoodFactory implements FoodFactory {@Overridepublic Food makeFood(String name) {if (name.equals("A")) {return new AmericanFoodA();} else if (name.equals("B")) {return new AmericanFoodB();} else {return null;}}
}

其中,ChineseFoodA、ChineseFoodB、AmericanFoodA、AmericanFoodB 都派生自 Food

客户端调用:

public class APP {public static void main(String[] args) {// 先选择一个具体的工厂FoodFactory factory = new ChineseFoodFactory();// 由第一步的工厂产生具体的对象,不同的工厂造出不一样的对象Food food = factory.makeFood("A");}
}

虽然都是调用 makeFood("A")  制作 A 类食物,但是,不同的工厂生产出来的完全不一样。

第一步,我们需要选取合适的工厂,然后第二步基本上和简单工厂一样。

核心在于,我们需要在第一步选好我们需要的工厂。比如,我们有 LogFactory 接口,实现类有 FileLogFactory 和 KafkaLogFactory,分别对应将日志写入文件和写入 Kafka 中,显然,我们客户端第一步就需要决定到底要实例化 FileLogFactory 还是 KafkaLogFactory,这将决定之后的所有的操作。

虽然简单,不过我也把所有的构件都画到一张图上,这样读者看着比较清晰:

 三、抽象工厂模式

当涉及到产品族的时候,就需要引入抽象工厂模式了。

一个经典的例子是造一台电脑。我们先不引入抽象工厂模式,看看怎么实现。

因为电脑是由许多的构件组成的,我们将 CPU 和主板进行抽象,然后 CPU 由 CPUFactory 生产,主板由 MainBoardFactory 生产,然后,我们再将 CPU 和主板搭配起来组合在一起,如下图:

 这个时候的客户端调用是这样的:

// 得到 Intel 的 CPU
CPUFactory cpuFactory = new IntelCPUFactory();
CPU cpu = intelCPUFactory.makeCPU();// 得到 AMD 的主板
MainBoardFactory mainBoardFactory = new AmdMainBoardFactory();
MainBoard mainBoard = mainBoardFactory.make();// 组装 CPU 和主板
Computer computer = new Computer(cpu, mainBoard);

单独看 CPU 工厂和主板工厂,它们分别是前面我们说的工厂模式。这种方式也容易扩展,因为要给电脑加硬盘的话,只需要加一个 HardDiskFactory 和相应的实现即可,不需要修改现有的工厂。

但是,这种方式有一个问题,那就是如果 Intel 家产的 CPU 和 AMD 产的主板不能兼容使用,那么这代码就容易出错,因为客户端并不知道它们不兼容,也就会错误地出现随意组合。

下面就是我们要说的产品族的概念,它代表了组成某个产品的一系列附件的集合:

当涉及到这种产品族的问题的时候,就需要抽象工厂模式来支持了。我们不再定义 CPU 工厂、主板工厂、硬盘工厂、显示屏工厂等等,我们直接定义电脑工厂,每个电脑工厂负责生产所有的设备,这样能保证肯定不存在兼容问题。

 这个时候,对于客户端来说,不再需要单独挑选 CPU厂商、主板厂商、硬盘厂商等,直接选择一家品牌工厂,品牌工厂会负责生产所有的东西,而且能保证肯定是兼容可用的。

public static void main(String[] args) {// 第一步就要选定一个“大厂”ComputerFactory cf = new AmdFactory();// 从这个大厂造 CPUCPU cpu = cf.makeCPU();// 从这个大厂造主板MainBoard board = cf.makeMainBoard();// 从这个大厂造硬盘HardDisk hardDisk = cf.makeHardDisk();// 将同一个厂子出来的 CPU、主板、硬盘组装在一起Computer result = new Computer(cpu, board, hardDisk);
}

当然,抽象工厂的问题也是显而易见的,比如我们要加个显示器,就需要修改所有的工厂,给所有的工厂都加上制造显示器的方法。这有点违反了对修改关闭,对扩展开放这个设计原则。

http://www.lryc.cn/news/65165.html

相关文章:

  • JAVA12新特性
  • Nginx 静态文件、反向代理、负载均衡、缓存、SSL/TLS 加密、gzip 压缩 等等
  • Linux设备驱动模型(一)
  • 【Python入门篇】——Python基础语法(标识符与运算符)
  • 扩展 VirtualBox 已分配磁盘的方法
  • 【LeetCode】646. 最长数对链
  • Makefile教程(Makefile的结构)
  • SpringMVC(后)SSM整合
  • 【博弈论】【第一章】博弈论导论
  • keil移植linux(makefile)
  • C++——类和对象(3)
  • itop-3568开发板驱动学习笔记(24)设备树(三)时钟实例分析
  • linux中使用docker部署微服务
  • 操作系统考试复习—第三章 优先级倒置 死锁问题
  • OpenHarmony送显流程分析
  • Java面试题字节流字符流
  • Self-Attention结构细节及计算过程
  • 在Ubuntu18.04中安装uWebSockets库
  • 【Fluent】接着上一次计算的结果继续计算,利用计算过程中得到的物理场(温度、速度、压力等)插值Interpolate文件初始化模型的方法
  • 第二十九章 使用消息订阅发布实现组件通信
  • Transformer的位置编码
  • Python学习简记
  • windows搭建一个FTP服务器超详细
  • u01使用率100%报错归档满的问题
  • Packet Tracer - 配置扩展 ACL - 场景 2
  • 最近面了12个人,发现这个测试基础题都答不上来...
  • JAVA基于Springboot框架的停车场管理系统开发实践和实现【附源码】
  • [230501] 4月29日考试真题第一篇|Temporary Pools
  • Qt中QString, int等数据转换以及Qt与Halcon联编程序打包
  • Android FlexboxLayout布局