一、抽象工厂模式的由来

  抽象工厂模式,最开始是为了解决操作系统按钮和窗体风格,而产生的一种设计模式。例如:在windows系统中,我们要用windows设定的按钮和窗体,当我们切换Linux系统时,要把按钮和窗体统一切换成Linux风格的。如何统一进行调换呢?于是就有人设计出了,windows是一个工厂,生产windows的窗体和按钮,Linux是一个工厂,生产Linux的窗体和按钮,通过切换工厂,来整体切换按钮和窗体风格。

  看了上面的描述,是不是感觉说了一堆废话呢?其实抽象工厂模式是从工厂方法模式演变来的。在工厂方法模式中,工厂是不是就只做一件事情呢?只返回一个产品呢?但是在实际业务当中,一个工厂,可能要做多个事情,比如上面描述的,要同时搞定按钮和窗体两件事情,搞定多个事情的工厂,就是抽象工厂。

二、抽象工厂模式的定义

  定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。工厂模式中的每一个形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构;而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。

  在上面一通官方的说法下,是不是又蒙蔽了呢?下面,我用通俗的话,解释一下子。

  提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类:这句话的意思就是,提供一个抽象工厂接口,这个接口定义多个产品调度方法,而不是一个产品调度的方法。无需指定他们的具体类,是说,接口定义的方法,返回的都是产品规范类型,使用者无需用具体产品类接收,用产品规范类接收即可。

  抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列:这句话里,提到了产品族和产品等级。好多地方也提到了这两个概念。产品族就是一个抽象工厂的实现类。多个产品族就是不同的工厂实现类。产品等级就是在一个抽象工厂类里,多个产品的调度。其实就是一个工厂类里的多个产品。

三、抽象工厂模式的角色

  抽象工厂模式的角色与工厂方法模式角色一样。只不过,抽象工厂里有多个产品等级而已。具体见《设计模式之工厂方法模式(Factory Method Pattern)

四、抽象工厂模式的实现

我们就以Windows系统和Liunx系统的窗体和按钮风格为例,实现抽象工厂模式。

首先,定义产品规范,抽象工厂都是产品等级的,这里,分为窗体产品和按钮产品两种:

  1. /**
  2. * 按钮产品规范
  3. */
  4. public interface Buttom {
  5. public void buttonStyle();
  6. }
  1. /**
  2. * 窗体产品规范
  3. */
  4. public interface Form {
  5. public void formStyle();
  6. }

分别实现linux系统的窗体、按钮产品和windows系统的窗体、按钮产品,如下代码:

  1. /**
  2. * linux系统按钮产品
  3. */
  4. public class LinuxButtom implements Buttom {
  5. @Override
  6. public void buttonStyle() {
  7. System.out.println("linux系统按钮");
  8. }
  9. }
  1. /**
  2. * linux系统窗体产品
  3. */
  4. public class LinuxFrom implements Form {
  5. @Override
  6. public void formStyle() {
  7. System.out.println("linux系统窗体");
  8. }
  9. }
  1. /**
  2. * windows系统按钮产品
  3. */
  4. public class WindowsButtom implements Buttom {
  5. @Override
  6. public void buttonStyle() {
  7. System.out.println("windows系统按钮");
  8. }
  9. }
  1. /**
  2. * windows系统窗体产品
  3. */
  4. public class WindowsForm implements Form {
  5. @Override
  6. public void formStyle() {
  7. System.out.println("windows窗体");
  8. }
  9. }

接下来,需要定义工厂了,工厂需要调度按钮和窗体两个产品,这就是两个产品等级,一个工厂里包含了两个方法,这个工厂就叫产品族。我们先定义抽象工厂:

  1. /**
  2. * 定义抽象工厂族,调度窗体和按钮两个产品等级
  3. */
  4. public abstract class AbstractFactory {
  5. //按钮产品等级
  6. public abstract void setButtom();
  7. //窗体产品等级
  8. public abstract void setForm();
  9. }

然后我们要实现抽象工厂,抽象工厂的实现类实现两个调度方法。如下代码:

  1. /**
  2. * linux系统工厂实现
  3. */
  4. public class LinuxAbstractFactory extends AbstractFactory {
  5. @Override
  6. public void setButtom() {
  7. new LinuxButtom().buttonStyle();
  8. }
  9.  
  10. @Override
  11. public void setForm() {
  12. new LinuxFrom().formStyle();
  13. }
  14. }
  1. /**
  2. * windows系统工厂实现类,实现两个产品等级
  3. */
  4. public class WindowsAbstractFactory extends AbstractFactory{
  5. @Override
  6. public void setButtom() {
  7. new WindowsButtom().buttonStyle();
  8. }
  9.  
  10. @Override
  11. public void setForm() {
  12. new WindowsForm().formStyle();
  13.  
  14. }
  15. }

作为设计模式的使用者,选择抽象工厂的实现类,来获得想要的产品,如下:

  1. /**
  2. * 使用者
  3. */
  4. public class AbstractFactoryUser {
  5. public static void main(String[] args) {
  6. //使用者选择实现工厂类,生成产品组合
  7. AbstractFactory factory=new WindowsAbstractFactory();
  8. factory.setButtom();
  9. factory.setForm();
  10. }
  11. }

五、抽象工厂模式在JDK中的实现

  抽象工厂模式在JDK中的典型应用是JDBC的Connection接口。前面我们已经分析了JDBC注册不同数据库的驱动,用的是简单工厂模式。在注册完驱动后,会得到不同驱动的Connection对象。Connection也是jdk提供的一个接口。所以驱动注册完后,需要实现Connection接口。Connection就相当于一个抽象工厂,里面定义了Statement、PreparedStatement、CallableStatement多个产品等级。Statement、PreparedStatement、CallableStatement都是产品规范接口,所以,数据库供应商在提供驱动时,需要同时提供一套Statement,PrepareStatement的产品实现类,还要提供Connection抽象工厂的实现类。这样,在使用者那里,不管切换哪个厂商的数据库驱动,只要面向抽象工厂类开发即可,无需知道内部实现。

  所以,在JDBC中,Driver利用的是简单工厂模式,其工厂类是DriverManager。Connection利用的是抽象工厂模式,它就是那个抽象工厂。

  由此可以看出,工厂模式设计的初衷就是,让使用者只面对接口进行开发即可,无需关心接口的内部继承和内部实现。



设计模式之抽象工厂模式(Abstract Factory Pattern)的更多相关文章

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

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

  2. 【设计模式】抽象工厂模式 Abstract Factory Pattern

    简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...

  3. 二十四种设计模式:抽象工厂模式(Abstract Factory Pattern)

    抽象工厂模式(Abstract Factory Pattern) 介绍提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 示例有Message和MessageModel,Messag ...

  4. 【UE4 设计模式】抽象工厂模式 Abstract Factory Pattern

    概述 描述 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类:具体的工厂负责实现具体的产品实例 抽象工厂中每个工厂可以创建多种产品(如苹果公司生产iPhone.iPad): 工厂方法 ...

  5. 设计模式 - 抽象工厂模式(abstract factory pattern) 具体解释

    抽象工厂模式(abstract factory pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/2709 ...

  6. Net设计模式实例之抽象工厂模式(Abstract Factory Pattern)

    一.抽象工厂模式简介(Bref Introduction) 抽象工厂模式(Abstract Factory Pattern),提供一个创建一系列相关或者相互依赖对象的接口,而无需制定他们的具体类.优点 ...

  7. C#设计模式——抽象工厂模式(Abstract Factory Pattern)

    一.概述在软件开发中,常常会需要创建一系列相互依赖的对象,同时,由于需求的变化,往往存在较多系列对象的创建工作.如果采用常规的创建方法(new),会造成客户程序和对象创建工作的紧耦合.对此,抽象工厂模 ...

  8. 六个创建模式之抽象工厂模式(Abstract Factory Pattern)

    问题: 使用工厂方法模式的主要问题是工厂类过多,每个产品对应一个工厂,不利于维护.因此可以考虑使用一个工厂创建一个产品族. 定义: 提供创建一些列相关或相互依赖的对象实例的接口,这些类可以称为一个产品 ...

  9. 23种设计模式之抽象工厂(Abstract Factory Pattern)

    抽象工厂 当想创建一组密不可分的对象时,工厂方法似乎就不够用了 抽象工厂是应对产品族概念的.应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品.比如,每个汽车公司可能要同时生产轿车.货车. ...

随机推荐

  1. 牛客小白月赛17 G 区间求和

    传送门 题意: 题解: 原本想着使用暴力方法: 1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream& ...

  2. 在Ubuntu虚拟机上搭建青岛OJ

    源码地址为:https://github.com/QingdaoU/OnlineJudge 可参考的文档为:https://github.com/QingdaoU/OnlineJudgeDeploy/ ...

  3. codeforces 876B

    B. Divisiblity of Differences time limit per test 1 second memory limit per test 512 megabytes input ...

  4. C语言经典面试题

    [题目]零值比较--BOOL,int,float,指针变量与零值比较的if语句. (首先给个提示:题目中要求的是零值比较,而非与0进行比较,在C++里"零值"的范围可就大了,可以是 ...

  5. TensorFlow+restore读取模型

    # 注意和前一或二篇Lenet训练并验证的文章从`y_conv = tf.nn.softmax(fc2)`起的不同 # 部分函数请参照前后2篇文章 import tensorflow as tf im ...

  6. js create Array ways All In One

    js create Array ways All In One ES6 const arr = [...document.querySelectorAll(`[data-dom="^div& ...

  7. js Nullish Coalescing Operator

    js Nullish Coalescing Operator 空值合并 const n = null ?? 'default string'; console.log(n); // "def ...

  8. uni-app 支持第三方 H5 离线包

    uni-app 支持第三方 H5 离线包 https://uniapp.dcloud.io/ https://github.com/dcloudio/uni-app refs xgqfrms 2012 ...

  9. 前端水印方案 All In One

    前端水印方案 All In One base64 用户名 图片水印 <div id="wm" style="pointer-events: none; width: ...

  10. how to input special symbol in macOS

    how to input special symbol in macOS 如何在 macOS 中输入特殊符号 1024 ≈ 1000 2^10 == 1024 约等于 1000, 方便用来表示 Opt ...