设计模式 | 抽象工厂模式

知识点三: 抽象工厂模式


一、概述

抽象工厂模式(Abstract Factory Pattern) 是基于工厂方法模式的一个延伸,是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它属于23种GOF设计模式的创建型设计模式。 抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。简单的说就是:

  • 围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
  • 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

定义:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。

在学习抽象工厂模式之前,最好先熟悉一下简单工厂模式以及工厂方法模式,这样对理解抽象工厂模式会有一定帮助,而且抽象工厂也是基于工厂方法模式的。


二、优缺点及使用场景

优点:

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:

产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

使用场景:

系统的产品多于一个产品族,而系统只消费某一族的产品。


三、模式中包含的角色和其职责以及实现方式

1.角色

抽象工厂(Creator)角色:抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。

具体工厂(Concrete Creator)角色:具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。

抽象产品(Product)角色:抽象模式所创建的所有对象的父类,它负责描述所有的实例锁共有的公共接口。

具体产品(Concrete Product)角色:抽象模式所创建的具体实例对象。

2.产品族和产品等级结构

前面提到过很多次产品族,下面来介绍一下什么是产品族:

在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法具有唯一性,一般情况下,一个具体工厂中只有一个或者一组重载的工厂方法。但是有时候我们希望一个工厂可以提供多个产品对象,而不是单一的产品对象,如一个电器工厂,它可以生产电视机、电冰箱、空调等多种电器,而不是只生产某一种电器。为了更好地理解抽象工厂模式,我们先引入两个概念:

  1. 产品等级结构产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
  2. 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。

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

产品族和产品等级结构.png

3.实现方式

我们将创建 ProductA 和 ProductB 接口和实现这些接口的实体类。下一步是创建抽象工厂类 Creator。接着定义工厂类 ConcreteCreator1 和 ConcreteCreator2,这两个工厂类都是扩展了 Creator。 如图:

抽象工厂方法.png


四、在java中的实现

1.抽象工厂角色

AnimalFactory.java

/**
 * @Description: 抽象工厂
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/4 20:12
 */
public interface AnimalFactory {
    //实例化狗
    public Animal getDog();

    //实例化猫
    public Animal getCat();
}

2.具体工厂角色

YellowFactory.java

/**
 * @Description: 产品族工厂:黄色的
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:57
 */
public class YellowFactory implements AnimalFactory {
    public Animal getDog() {
        return new YellowDog();
    }

    public Animal getCat() {
        return new YellowCat();
    }
}

BlackFactory.java

/**
 * @Description: 产品族工厂:黑色的
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:58
 */
public class BlackFactory implements AnimalFactory {
    public Animal getDog() {
        return new BlackDog();
    }

    public Animal getCat() {
        return new BlackCat();
    }
}

3.抽象产品角色

Animal.java

/**
 * @Description: 抽象产品
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/2 16:23
 */
public interface Animal {
    public void get();
}

Cat.java

/**
 * @Description: 抽象产品类
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/2 16:24
 */
public abstract class Cat implements Animal {
    public abstract void get();
}

Dog.java

/**
 * @Description: 抽象产品类
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/2 16:23
 */
public abstract class Dog implements Animal {
    public abstract void get();
}

4.具体产品角色

YellowCat.java

/**
 * @Description: 具体产品:黄猫
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:44
 */
public class YellowCat extends Cat {
    public void get() {
        System.out.println("获得黄猫");
    }
}

YellowDog.java

/**
 * @Description: 具体产品:黄狗
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:44
 */
public class YellowDog extends Dog {
    public void get() {
        System.out.println("获得黄狗");
    }
}

BlackCat.java

/**
 * @Description:  具体产品:黑猫
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:46
 */
public class BlackCat extends Cat {
    public void get() {
        System.out.println("获得黑猫");
    }
}

BlackDog.java

/**
 * @Description: 具体产品:黑狗
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:44
 */
public class BlackDog extends Dog {
    public void get() {
        System.out.println("获得黑狗");
    }
}

5.测试类

MainClass.java

/**
 * @Description: 主方法
 * @Author: Ling.D.S
 * @Date: Created in 2018/11/5 20:59
 */
public class MainClass {
    public static void main(String[] args) {

        AnimalFactory yFactory = new YellowFactory();
        Animal yDog = yFactory.getDog();
        yDog.get();
        Animal yCat = yFactory.getCat();
        yCat.get();

        AnimalFactory bFactory = new BlackFactory();
        Animal bDog = bFactory.getDog();
        bDog.get();
        Animal bCat = bFactory.getCat();
        bCat.get();
    }
}

结果:

结果.png


五、抽象工厂模式和工厂方法模式的区别

抽象工厂是可以生产多个产品的,例如 YellowFactory里可以生产 YellowDog以及 YellowCat两个产品,而这两个产品又是属于一个系列的,因为它们都是属于Animal的子类。而工厂方法模式则只能生产一个产品,例如之前的 CatFactory 里就只可以生产一个 Cat产品。

示意图:

抽象工厂模式和工厂模式的差别.png


转载请注明原地址,宋德凌的博客:http://CoderOfSong.github.io 谢谢!

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦