1、抽象工厂模式的定义

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

2、抽象工厂模式特性

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

(2)主要解决:主要解决接口选择的问题。

(3)何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

(4)如何解决:在一个产品族里面,定义多个产品。

(5)关键代码:在一个工厂里聚合多个同类产品。

3、抽象工厂模式的优缺点及应用场景

(1)优点:

   1. 具体产品在应用层的代码隔离,无需关系创建的细节

   2. 将一个系列的产品统一到一起创建

(2)缺点:

   1. 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难;

   2. 增加了系统的抽象性和理解难度

(3)使用场景:

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

   2. 在很多软件系统中需要更换界面主题或者一键换肤。

   3. DAO层支持多种类型的数据库,动态切换时。

   4. 不同操作系统代码差异化,可以切换不同操作系统时。

(4)注意事项:

  产品族难扩展,产品等级易扩展。

理解产品族和产品等级

   产品族:一个品牌下面的所有产品;例如小米下面的打印机,扫码枪 称为小米的产品族;
   产品等级:多个品牌下面的同种产品;例如惠普和小米下面的打印机 称为一个产品等级;

4、抽象工厂模式的结构和说明

  • AbstractFactory:这是抽象工厂模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
  • ConcreteFactory:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。它由具体的类来实现。
  • AbstractProduct:它是具体产品继承的父类或者是实现的接口。在java中一般由抽象类或者接口来实现。
  • Product:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现

5、抽象工厂模式示例

5.1 题目

  假设当前电脑上接了3种类型设备,每种类型的还有不同的厂商,打印机(惠普打印机,小米打印机。。。等等),扫码枪(惠普扫码枪,小米扫码枪。。。等等),身份证读卡器(惠普读卡器,小米读卡器。。。等等)

如何设计一个插件系统

  需要符合以下要求:

  1. 每种类型的都要能做到动态切换,比如打印机,可以随意切换不同的厂商。
  2. 需要考虑扩展
  3. 需要考虑代码复用

5.2 分析

  打印机、扫码枪和读卡器是我们需要的产品,生产打印机、扫码枪和读卡器的惠普和小米是我们的工厂。

5.3 代码实现

5.3.1 创建打印机、扫码枪和读卡器的接口

读卡器接口

public interface IIdCard {
   
    void read();
}

扫码枪接口

public interface ISaoma {
   
    void saoma();
}

打印机接口

public interface IPrint{
   
    void print();
}

5.3.2 创建实现上述接口的实现类

小米读卡器

public class MiCard implements IIdCard{
   
    @Override
    public void read() {
   
        System.out.println("Inside MiCard::read() method.");
    }
}

小米扫码枪

public class MISaoma implements ISaoma{
   
    @Override
    public void saoma() {
   
		System.out.println("Inside MISaoma::saoma() method.");
    }
}

小米打印机

public class MiPrint extends Miaaa {
   
    @Override
    public void print() {
   
        System.out.println("Inside MiPrint::print() method.");
    }
}

惠普读卡器

public class HPCard implements IIdCard{
   
    @Override
    public void read() {
   
        System.out.println("Inside HPCard::read() method.");
    }
}

惠普扫码枪

public class HPSaoma implements ISaoma{
   
    @Override
    public void saoma() {
   
        System.out.println("Inside HPSaoma::saoma() method.");
    }
}

惠普打印机

public class HPPrint implements IPrint{
   
    @Override
    public void print() {
   
        System.out.println("Inside HPPrint::print() method.");
    }
}

5.3.3 创建工厂模式的核心,根据参数决定获取那个产品族

//抽象工厂模式的核心,根据参数决定获取那个产品族
public abstract class AbStractFactory {
   
    public abstract IPrint getPrint(String name);
    public abstract IIdCard getCard(String name);
    public abstract ISaoma getSaoma(String name);
}

5.3.4 创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象

读卡器工厂

public class CardFactory extends AbStractFactory {
   

    @Override
    public IPrint getPrint(String name) {
   
        return null;
    }

    @Override
    public IIdCard getCard(String name) {
   
        if ("Mi".equalsIgnoreCase(name)){
   
            return new MiCard();
        }else if ("HP".equalsIgnoreCase(name)){
   
            return new HPCard();
        }
        return null;
    }

    @Override
    public ISaoma getSaoma(String name) {
   
        return null;
    }
}

扫码枪工厂

public class SaomaFactory extends AbStractFactory {
   

    @Override
    public IPrint getPrint(String name) {
   
        return null;
    }

    @Override
    public IIdCard getCard(String name) {
   
        return null;
    }

    @Override
    public ISaoma getSaoma(String name) {
   
        if ("Mi".equalsIgnoreCase(name)){
   
            return new MISaoma();
        }else if ("HP".equalsIgnoreCase(name)){
   
            return new HPSaoma();
        }
        return null;
    }
}

打印机工厂

public class PrintFactory extends AbStractFactory {
   

    @Override
    public IPrint getPrint(String name) {
   
        if ("Mi".equalsIgnoreCase(name)){
   
            return new MiPrint();
        }else if ("HP".equalsIgnoreCase(name)){
   
            return new HPPrint();
        }
        return null;
    }

    @Override
    public IIdCard getCard(String name) {
   
        return null;
    }

    @Override
    public ISaoma getSaoma(String name) {
   
        return null;
    }
}

5.3.5 创建一个工厂创造器/生成器类,通过传递参数来获取工厂

public abstract class FactoryProducer {
   
    static AbStractFactory getFactory(String s) {
   
        if ("Card".equalsIgnoreCase(s)){
   //返回读卡器工厂
            return new CardFactory();
        }else if ("Print".equalsIgnoreCase(s)){
   //返回打印机工厂
            return new PrintFactory();
        }else if ("Saoma".equalsIgnoreCase(s)){
   //返回扫码枪工厂
            return new SaomaFactory();
        }
        return null;
    }
}

5.3.6 使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象

public class AbstractFactoryPatternDemo {
   
    public static void main(String[] args) {
   
        System.out.println("=============读卡器================");
        //获取读卡器工厂
        AbStractFactory cardFactory= FactoryProducer.getFactory("Card");
        //获取小米读卡器的对象
        IIdCard miCard= cardFactory.getCard("Mi");
        //调用小米读卡器的 read 方法
        miCard.read();
        //获取惠普读卡器的对象
        IIdCard HPCard= cardFactory.getCard("HP");
        //调用惠普读卡器的 read 方法
        HPCard.read();

        System.out.println("=============扫码枪================");
        //获取扫码枪工厂
        AbStractFactory saoMaFactory= FactoryProducer.getFactory("SaoMa");
        //获取小米读卡器的对象
        ISaoma miSaoma= saoMaFactory.getSaoma("Mi");
        //调用小米读卡器的 saoma 方法
        miSaoma.saoma();
        //获取惠普读卡器的对象
        ISaoma HPSaoma= saoMaFactory.getSaoma("HP");
        //调用惠普读卡器的 read 方法
        HPSaoma.saoma();

        System.out.println("=============打印机================");
        //获取扫码枪工厂
        AbStractFactory printFactory= FactoryProducer.getFactory("print");
        //获取小米读卡器的对象
        IPrint miPrint= printFactory.getPrint("Mi");
        //调用小米读卡器的 saoma 方法
        miPrint.print();
        //获取惠普读卡器的对象
        IPrint HPPrint= printFactory.getPrint("HP");
        //调用惠普读卡器的 read 方法
        HPPrint.print();
    }
}

5.3.7 测试结果


最后根据题目的要求,工厂自由组合即可。