抽象工厂模式(JAVA反射)

实例代码(JAVA):模式动机

在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

为了更清晰地理解工厂方法模式,需要先引入两个概念:

产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。

产品族与产品等级结构示意图:

当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。

抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

模式定义

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

模式结构

抽象工厂模式包含如下角色:

AbstractFactory:抽象工厂

ConcreteFactory:具体工厂

AbstractProduct:抽象产品

Product:具体产品

模式分析

抽象工厂类的典型代码如下:

1 public abstract class AbstractFactory
2 {
3     public abstract AbstractProductA createProductA();
4     public abstract AbstractProductB createProductB();
5 }

 具体工厂类的典型代码如下:

 1 public class ConcreteFactory1 extends AbstractFactory
 2 {
 3     public AbstractProductA createProductA()
 4     {
 5         return new ConcreteProductA1();
 6     }
 7     public AbstractProductB createProductB()
 8     {
 9         return new ConcreteProductB1();
10     }
11 }

模式实例与解析

实例一:电器工厂

? 一个电器工厂可以产生多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL工厂可以生产TCL电视机、TCL空调等,相同品牌的电器构成一个产品族,而相同类型的电器构成了一个产品等级结构,现使用抽象工厂模式模拟该场景。

实例代码(JAVA):

  1 //抽象产品 Television
  2 public interface Television
  3 {
  4     public void play();
  5 }
  6
  7 //具体产品 HaierTelevision
  8 public class HaierTelevision implements Television
  9 {
 10     public void play()
 11     {
 12         System.out.println("海尔电视机播放中......");
 13     }
 14 }
 15
 16 //具体产品 TCLTelevision
 17 public class TCLTelevision implements Television
 18 {
 19     public void play()
 20     {
 21         System.out.println("TCL电视机播放中......");
 22     }
 23 }
 24
 25 //抽象产品 AirConditioner
 26 public interface AirConditioner
 27 {
 28     public void changeTemperature();
 29 }
 30
 31 //具体产品 HaierAirConditioner
 32 public class HaierAirConditioner implements AirConditioner
 33 {
 34     public void changeTemperature()
 35     {
 36         System.out.println("海尔空调温度改变中......");
 37     }
 38 }
 39
 40 //具体产品 TCLAirConditioner
 41 public class TCLAirConditioner implements AirConditioner
 42 {
 43     public void changeTemperature()
 44     {
 45         System.out.println("TCL空调温度改变中......");
 46     }
 47 }
 48
 49 //抽象工厂 EFactory
 50 public interface EFactory
 51 {
 52     public Television produceTelevision();
 53     public AirConditioner produceAirConditioner();
 54 }
 55
 56 //具体工厂 HaierFactory
 57 public class HaierFactory implements EFactory
 58 {
 59     public Television produceTelevision()
 60     {
 61         return new HaierTelevision();
 62     }
 63
 64     public AirConditioner produceAirConditioner()
 65     {
 66         return new HaierAirConditioner();
 67     }
 68 }
 69
 70 //具体工厂 TCLFactory
 71 public class TCLFactory implements EFactory
 72 {
 73     public Television produceTelevision()
 74     {
 75         return new TCLTelevision();
 76     }
 77
 78     public AirConditioner produceAirConditioner()
 79     {
 80         return new TCLAirConditioner();
 81     }
 82 }
 83
 84 //配置文件 config.xml
 85 <?xml version="1.0"?>
 86 <config>
 87     <className>HaierFactory</className>
 88 </config>
 89
 90 //通过反射获得具体工厂的实例 XMLUtil
 91 import javax.xml.parsers.*;
 92 import org.w3c.dom.*;
 93 import org.xml.sax.SAXException;
 94 import java.io.*;
 95 public class XMLUtil
 96 {
 97 //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
 98     public static Object getBean()
 99     {
100         try
101         {
102             //创建文档对象
103             DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
104             DocumentBuilder builder = dFactory.newDocumentBuilder();
105             Document doc;
106             doc = builder.parse(new File("config.xml"));
107
108             //获取包含类名的文本节点
109             NodeList nl = doc.getElementsByTagName("className");
110             Node classNode=nl.item(0).getFirstChild();
111             String cName=classNode.getNodeValue();
112
113             //通过类名生成实例对象并将其返回
114             Class c=Class.forName(cName);
115               Object obj=c.newInstance();
116             return obj;
117            }
118                catch(Exception e)
119                {
120                    e.printStackTrace();
121                    return null;
122                }
123         }
124 }
125
126 //客户端类 Client
127 public class Client
128 {
129     public static void main(String args[])
130     {
131          try
132          {
133              EFactory factory;
134              Television tv;
135              AirConditioner ac;
136              factory=(EFactory)XMLUtil.getBean();
137              tv=factory.produceTelevision();
138              tv.play();
139              ac=factory.produceAirConditioner();
140              ac.changeTemperature();
141          }
142          catch(Exception e)
143          {
144              System.out.println(e.getMessage());
145          }
146     }
147 }

实例代码(C++):

  1 // 抽象工厂模式
  2 #include <iostream>
  3 using namespace std;
  4
  5 //抽象产品类 Television
  6 class Television
  7 {
  8 public:
  9     virtual void play() = 0;
 10 };
 11
 12 //具体产品类 HaierTelevision
 13 class HaierTelevision:public Television
 14 {
 15 public:
 16     void play() override
 17     {
 18         cout << "海尔电视播放中..." << endl;
 19     }
 20 };
 21
 22 //具体产品类 TCLTelevision
 23 class TCLTelevision : public Television
 24 {
 25 public:
 26     void play() override
 27     {
 28         cout << "TCL电视播放中..." << endl;
 29     }
 30 };
 31
 32 //抽象产品 AirConditioner
 33 class AirConditioner
 34 {
 35 public:
 36     virtual void changeTemperature() = 0;
 37 };
 38
 39 //具体产品 HaierAirConditioner
 40 class HaierAirConditioner : public AirConditioner
 41 {
 42 public:
 43     void changeTemperature() override
 44     {
 45         cout << "海尔空调温度改变中..." << endl;
 46     }
 47 };
 48
 49 //具体产品 TCLAirConditioner
 50 class TCLAirConditioner : public AirConditioner
 51 {
 52 public:
 53     void changeTemperature() override
 54     {
 55         cout << "TCL空调温度改变中..." << endl;
 56     }
 57 };
 58
 59 //抽象工厂 EFactory
 60 class EFactory
 61 {
 62 public:
 63     virtual Television* productTelevision() = 0;
 64     virtual AirConditioner* productAirConditioner() = 0;
 65 };
 66
 67 //具体工厂 HaierFactory
 68 class HaierFactory : public EFactory
 69 {
 70 public:
 71     Television* productTelevision() override
 72     {
 73         return new HaierTelevision();
 74     }
 75
 76     AirConditioner* productAirConditioner() override
 77     {
 78         return new HaierAirConditioner();
 79     }
 80 };
 81
 82 //具体工厂 TCLFactory
 83 class TCLFactory : public EFactory
 84 {
 85 public:
 86     Television* productTelevision() override
 87     {
 88         return new TCLTelevision();
 89     }
 90
 91     AirConditioner* productAirConditioner() override
 92     {
 93         return new TCLAirConditioner();
 94     }
 95 };
 96
 97 //客户端
 98 int main()
 99 {
100     EFactory* factory;
101     Television* tv;
102     AirConditioner* ac;
103     factory = new HaierFactory();
104     tv = factory->productTelevision();
105     tv->play();
106     ac = factory->productAirConditioner();
107     ac->changeTemperature();
108
109     factory = new TCLFactory();
110     tv = factory->productTelevision();
111     tv->play();
112     ac = factory->productAirConditioner();
113     ac->changeTemperature();
114     return 0;
115 }

运行结果:

实例二:数据库操作工厂

? 某系统为了改进数据库操作的性能,自定义数据库连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象,如提供Oracle或SQL Server专用连接类和语句类,而且用户可以通过配置文件等方式根据实际需要动态更换系统数据库。使用抽象工厂模式设计该系统。

模式优缺点

优点

? 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。

? 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。

? 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

缺点

? 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。

? 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)

模式适用环境

在以下情况下可以使用抽象工厂模式:

? 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。

? 系统中有多于一个的产品族,而每次只使用其中某一产品族。

? 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。

? 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

模式应用

(1) Java SE AWT(抽象窗口工具包)

? 在Java语言的AWT(抽象窗口工具包)中就使用了抽象工厂模式,它使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。

(2) 在很多软件系统中需要更换界面主题,要求界面中的按钮、文本框、背景色等一起发生改变时,可以使用抽象工厂模式进行设计。

模式扩展

“开闭原则”的倾斜性

? “开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:

? (1) 增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂即可,对已有代码无须做任何修改。

? (2) 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。

? 抽象工厂模式的这种性质称为“开闭原则”的倾斜性,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,但不能为新的产品等级结构的增加提供这样的方便。

工厂模式的退化

? 当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

原文地址:https://www.cnblogs.com/WindSun/p/10253248.html

时间: 2024-10-07 08:03:55

抽象工厂模式(JAVA反射)的相关文章

大话设计模式_抽象工厂模式(Java代码)

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类. 简单描述:有多种抽象产品,并且每种抽象产品都有多个具体产品.一个抽象工厂,提供多个具体工厂,每个工厂则提供不同种类的具体产品. 大话设计模式中的截图: 例子代码: AbstractProductA类: 1 package com.longsheng.abstractfactory; 2 3 public abstract class AbstractProductA { 4 5 public abstract v

抽象工厂模式java实现

上一篇博文:http://blog.csdn.net/huruzun/article/details/26715369  已经很详细的讲述了工厂模式,这篇将讲述与工厂模式关系很密切的抽象工厂模式. 工厂模式中披萨店设计已经很棒了:具有弹性框架,而且遵循设计原则. 现在披萨店的关键就在如何控制加盟店原料流程? 如何确保加盟店原料的一致? 通过工厂模式,我们很快就能发现,现在我们需要建造原料工厂来确保加盟店原料的一致性. package abstrctFactory; public interfac

工厂模式——抽象工厂模式(+反射)

这里又出现了一个抽象工厂模式,这个抽象工厂模式又是什么呢? 我们现在来模拟一个场景,现在用的是Mysql数据库,明天让你更换为Oracle数据库.此时,想想要做多少的改动.但我们如果用工厂模式,这会让你节省大量时间. 首先,我们用工厂方法模式来设计这个程序. 我们画出类的UML图. IFactory作为工厂类的接口,有两个子类,分别用来构造不同的实例. IFactory工厂接口代码如下: package day_3_facoryMethod_db; /** * 数据库工厂类 * @author

工厂模式三部曲:抽象工厂模式

工厂模式三部曲:简单工厂模式 工厂模式三部曲:工厂方法模式 前言 这是工厂模式三部曲中的最后一篇了,在这篇文章中将会讲述抽象工厂模式,抽象工厂模式正如其名字一样,非常抽象.但是抽象工厂模式的功能却十分强大,对抽象工厂的利用也非常好. 这篇文章中会像本系列第一篇一样,给出普通实现方式和使用了反射机制的实现两种代码,并且会说明这两种实现方式的区别.并且在文章的最后,会将这三种模式放在一起,对这三种工厂模式进行总结. 本人理解可能不够深刻,这一系列文章中存在的问题,欢迎大家提出,谢谢! 什么是抽象工厂

JAVA设计模式之抽象工厂模式 (转)

前面已经介绍过简单工厂模式和工厂方法模式,这里继续介绍第三种工厂模式-抽象工厂模式,还是以汽车的制造为例. 例子背景: 随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件.于是这个工厂开始生产空调和发动机,用来组装汽车.这时候工厂有两个系列的产品:空调和发动机.宝马320系列配置A型号空调和A型号发动机,宝马230系列配置B型号空调和B型号发动机. 概念: 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象.比如宝马320系列使用空调型号A和发动机型号A,而宝

抽象工厂模式的C++、Java实现

1.抽象工厂模式UML 图1. 抽象工厂模式的UML 2.C++实现 C++实现类图为: 图2. 抽象工厂模式的C++实现类图 其中,AbstractFactory的实现代码为: 1 //抽象工厂类基类. 2 class AbstractFactory 3 { 4 public: 5 AbstractFactory(); 6 ~AbstractFactory(); 7 8 //创建具体的产品的抽象工厂方法. 9 //创建A类对象. 10 virtual ProductA * CreateProd

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

抽象工厂设计模式 1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用.来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关.是具体工厂角色必须实现的接口或者必须继承的父类.在java中它由抽象类或者接口来实现.具体工厂角色:它含有和具体业务逻辑有关的代码.由应用程序调用以创建对应的具体产品的对象.在java中它由具体的类来实现.抽象产品角色:它是具体产品继承的父类或者是实现的接口.在java中一般

反射+抽象工厂模式

这里通过一个DEMO介绍反射配合抽象工厂模式的运用.大概业务背景就是在实际业务过程中,可能要替换数据库,具体代码如下: 1.User实体类 class User { private int id; private string name; public int Id { get { return id; } set { id = value; } } public string Name { get { return name; } set { name = value; } } } 2.操作U

抽象工厂模式(Java与Kotlin版)

前文推送 设计模式 简单工厂模式(Java与Kotlin版) 工厂方法模式(Java与Kotlin版) Kotlin基础知识 Kotlin入门第一课:从对比Java开始 Kotlin入门第二课:集合操作 Kotlin入门第三课:数据类型 初次尝试用Kotlin实现Android项目 1. 定义 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类.抽象工厂模式又称为Kit模式,属于对象创建型模式. 2. 结构 Abs