设计模式-04抽象工厂模式

文章中涉及到的代码,请自行下载
https://gitee.com/pan_xiao_lei123/designmode.git

前面介绍的工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。

同种类称为同等级,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。

本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,图 1 所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。

文章目录

  • 设计模式-04抽象工厂模式
    • 模式的定义与特点
    • 模式的结构与实现
    • 模式的应用实例
    • 模式的应用场景
    • 模式的扩展

模式的定义与特点

抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

使用抽象工厂模式一般要满足以下条件。
● 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
● 系统一次只可能消费其中某一族产品,即同族的产品一起使用。

抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
● 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
● 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
● 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。

其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。

模式的结构与实现

抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。现在我们来分析其基本结构和实现方法。
1. 模式的结构
抽象工厂模式的主要角色如下。
1、抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
2、具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
3、抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
4、具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

抽象工厂模式的结构图如图 2 所示。

2. 模式的实现
从图 2 可以看出抽象工厂模式的结构同工厂方法模式的结构相似,不同的是其产品的种类不止一个,所以创建产品的方法也不止一个。下面给出抽象工厂和具体工厂的代码。
(1) 抽象工厂:提供了产品的生成方法。

interface AbstractFactory {public Product1 newProduct1();public Product2 newProduct2();
}

(2) 具体工厂:实现了产品的生成方法。

class ConcreteFactory1 implements AbstractFactory {public Product1 newProduct1() {System.out.println("具体工厂 1 生成-->具体产品 11...");return new ConcreteProduct11();}public Product2 newProduct2() {System.out.println("具体工厂 1 生成-->具体产品 21...");return new ConcreteProduct21();}
}

模式的应用实例

【例1】用抽象工厂模式设计农场类。

分析:农场中除了像畜牧场一样可以养动物,还可以培养植物,如养马、养牛、种菜、种水果等,所以本实例比前面介绍的畜牧场类复杂,必须用抽象工厂模式来实现。

本例用抽象工厂模式来设计两个农场,一个是韶关农场用于养牛和种菜,一个是上饶农场用于养马和种水果,可以在以上两个农场中定义一个生成动物的方法 newAnimal() 和一个培养植物的方法 newPlant()。

对马类、牛类、蔬菜类和水果类等具体产品类,由于要显示它们的图像,所以它们的构造函数中用到了 JPanel、JLabel 和 ImageIcon 等组件,并定义一个 show() 方法来显示它们。

客户端程序通过对象生成器类 ReadXML 读取 XML 配置文件中的数据来决定养什么动物和培养什么植物(点此下载 XML 文件)。其结构图如图 3 所示。

package AbstractFactory;import java.awt.*;
import javax.swing.*;public class FarmTest {public static void main(String[] args) {try {Farm f;Animal a;Plant p;f = (Farm) ReadXML.getObject();a = f.newAnimal();p = f.newPlant();a.show();p.show();} catch (Exception e) {System.out.println(e.getMessage());}}
}//抽象产品:动物类
interface Animal {public void show();
}//具体产品:马类
class Horse implements Animal {JScrollPane sp;JFrame jf = new JFrame("抽象工厂模式测试");public Horse() {Container contentPane = jf.getContentPane();JPanel p1 = new JPanel();p1.setLayout(new GridLayout(1, 1));p1.setBorder(BorderFactory.createTitledBorder("动物:马"));sp = new JScrollPane(p1);contentPane.add(sp, BorderLayout.CENTER);JLabel l1 = new JLabel(new ImageIcon("src/A_Horse.jpg"));p1.add(l1);jf.pack();jf.setVisible(false);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭}public void show() {jf.setVisible(true);}
}//具体产品:牛类
class Cattle implements Animal {JScrollPane sp;JFrame jf = new JFrame("抽象工厂模式测试");public Cattle() {Container contentPane = jf.getContentPane();JPanel p1 = new JPanel();p1.setLayout(new GridLayout(1, 1));p1.setBorder(BorderFactory.createTitledBorder("动物:牛"));sp = new JScrollPane(p1);contentPane.add(sp, BorderLayout.CENTER);JLabel l1 = new JLabel(new ImageIcon("src/A_Cattle.jpg"));p1.add(l1);jf.pack();jf.setVisible(false);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭}public void show() {jf.setVisible(true);}
}//抽象产品:植物类
interface Plant {public void show();
}//具体产品:水果类
class Fruitage implements Plant {JScrollPane sp;JFrame jf = new JFrame("抽象工厂模式测试");public Fruitage() {Container contentPane = jf.getContentPane();JPanel p1 = new JPanel();p1.setLayout(new GridLayout(1, 1));p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));sp = new JScrollPane(p1);contentPane.add(sp, BorderLayout.CENTER);JLabel l1 = new JLabel(new ImageIcon("src/P_Fruitage.jpg"));p1.add(l1);jf.pack();jf.setVisible(false);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭}public void show() {jf.setVisible(true);}
}//具体产品:蔬菜类
class Vegetables implements Plant {JScrollPane sp;JFrame jf = new JFrame("抽象工厂模式测试");public Vegetables() {Container contentPane = jf.getContentPane();JPanel p1 = new JPanel();p1.setLayout(new GridLayout(1, 1));p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));sp = new JScrollPane(p1);contentPane.add(sp, BorderLayout.CENTER);JLabel l1 = new JLabel(new ImageIcon("src/P_Vegetables.jpg"));p1.add(l1);jf.pack();jf.setVisible(false);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭}public void show() {jf.setVisible(true);}
}//抽象工厂:农场类
interface Farm {public Animal newAnimal();public Plant newPlant();
}//具体工厂:韶关农场类
class SGfarm implements Farm {public Animal newAnimal() {System.out.println("新牛出生!");return new Cattle();}public Plant newPlant() {System.out.println("蔬菜长成!");return new Vegetables();}
}//具体工厂:上饶农场类
class SRfarm implements Farm {public Animal newAnimal() {System.out.println("新马出生!");return new Horse();}public Plant newPlant() {System.out.println("水果长成!");return new Fruitage();}
}
package AbstractFactory;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
class ReadXML {public static Object getObject() {try {DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc;doc = builder.parse(new File("src/AbstractFactory/config.xml"));NodeList nl = doc.getElementsByTagName("className");Node classNode = nl.item(0).getFirstChild();String cName = "AbstractFactory." + classNode.getNodeValue();System.out.println("新类名:" + cName);Class<?> c = Class.forName(cName);Object obj = c.newInstance();return obj;} catch (Exception e) {e.printStackTrace();return null;}}
}

模式的应用场景

抽象工厂模式最早的应用是用于创建属于不同操作系统的视窗构件。如 Java 的 AWT 中的 Button 和 Text 等构件在 Windows 和 UNIX 中的本地实现是不同的。

抽象工厂模式通常适用于以下场景:
1、当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
2、系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
3、系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

模式的扩展

抽象工厂模式的扩展有一定的“开闭原则”倾斜性:
1、当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
2、当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。

另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。

设计模式-04抽象工厂模式相关推荐

  1. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页] [源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Facto ...

  2. 设计模式系列·抽象工厂模式

    前言 以小说的笔法写的设计模式系列文章,你绝对看得懂![首发于公众号:"聊聊代码"] 设计模式系列·王小二需求历险记(一) 设计模式系列·王小二需求历险记(二) 设计模式系列·封装 ...

  3. 设计模式三—抽象工厂模式

    设计模式三-抽象工厂模式 一.定义 抽象工厂模式是工厂方法模式的进一步抽象.如果产品簇中只有一种产品,则退化为工厂方法模式. 二.原理图 三.代码实例 * 苹果和土豆是园丁1的杰作 * 葡萄和西红柿是 ...

  4. 设计模式复习-抽象工厂模式

    设计模式复习-抽象工厂模式 有两种硬件,PC和Phone,有两种系统,Windows和Linux,现在假设PC和Phone上全都能安装这两个系统,并且将来硬件不会在变化,但是系统可能需要扩展,比如扩展 ...

  5. 设计模式之四(抽象工厂模式第三回合)

    原文:设计模式之四(抽象工厂模式第三回合) 前言 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如I ...

  6. python抽象工厂模式_Python设计模式之抽象工厂模式

    Python设计模式之抽象工厂模式 这篇文章主要为大家详细介绍了Python设计模式之抽象工厂模式,感兴趣的小伙伴们可以参考一下 python面向对象编程入门,我们需要不断学习进步 "&qu ...

  7. C#设计模式(4)——抽象工厂模式

    C#设计模式(4)--抽象工厂模式 一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法 ...

  8. 抽象工厂模式设计模式_21世纪的设计模式:抽象工厂模式

    抽象工厂模式设计模式 这是我的演讲的第二部分," 21世纪的设计模式" . 此模式在Java代码中到处都有使用,尤其是在更多"企业"代码库中. 它涉及一个接口和 ...

  9. 21世纪的设计模式:抽象工厂模式

    这是我的演讲的第二部分," 21世纪的设计模式" . 此模式在Java代码中到处都有使用,尤其是在更多"企业"代码库中. 它涉及一个接口和一个实现. 该界面如下 ...

最新文章

  1. SpringMVC工作环境搭建 配置文件
  2. NetBeans 时事通讯(刊号 # 146 - May 13, 2011)
  3. [UE4] 内容浏览器不显示继承自 None 的类
  4. 【文章收藏】阿里云破了四个世界纪录
  5. idea拦截了html中的静态资源,IDEA配置静态资源热加载操作(Springboot修改静态资源不重启)...
  6. 编辑器之神Vim总结
  7. 如何有效地刷算法题?
  8. 列表查询组件代码, 简化拼接条件SQL语句的麻烦
  9. 在Lua中“优雅”地使用Protobuf
  10. linearlayout布局的属性 gravity layout_gravity layout_weight
  11. matlab 取矩阵上三角元素,MATLAB triu():提取上三角矩阵
  12. 关于消防装备管理系统于消防装备管理中应用的论述
  13. 17互联网产品的交互设计(文智老师公开课笔记)
  14. 简单猜年龄游戏Python代码
  15. 女生适合学酒店管理 电子商务还是计算机,读中专是学旅游服务与酒店管理好呢?还是计算机好呢?这两个专业那个更好呢?...
  16. Excel插件获取单元格批注以及设置批注
  17. AutoJs学习-实现自动发邮件
  18. 怎么打造小红书爆款笔记账号?教你几招
  19. php redis incr秒杀,Redis瞬时高并发秒杀方案总结
  20. python例子高考志愿填报系统入口_2019年四川高考志愿填报系统入口网址登录入口(最新)...

热门文章

  1. 蓝桥杯java抽签_第七届蓝桥杯Java A——抽签
  2. 计算机网络.第一节课.笔记.有效数据率、OSI七层结构、TCP/IP四层、网络协议三要素、时延、广域网WAN、局域网LAN、电路交换、报文交换、分组交换
  3. object-fit : CSS 图片自适应
  4. 织梦dedecms文章发布日期时间调用标签大全
  5. 手机文档被删除怎么恢复,如何恢复
  6. 小鱼易连打造基于互联网环境下的高清视频会议终端
  7. 弘辽科技:拼多多拼单价格怎么算?拼单规则是什么?
  8. MySQL按时间日期查询表数据做数据统计
  9. linux脚本base64加密当时,用shell解密base64加密的文本的例子
  10. Python返回列表中某个元素的出现次数list.count()方法