抽象工厂设计模式

产品族

  • 所谓产品族,是指位于不同产品等级结构中,功能相关联的产品组成的家族

需求

  • 假设现在引入一种新的产品
  • 按照工厂方法模式的写法,自然就要在具体的苹果工厂类里再增加一个新的方法,返回新的苹果实例
  • 同时也要增加新的苹果这个新的产品
  • 其他水果工厂类是一样的做法
  • 这明显违背了 OCP (开闭) 原则
  • 苹果工厂类既能生成进口苹果也能生产国产苹果,违背了单一职责原则

抽象工厂

  • 是一种为访问类提供一个创建一组相关对象的接口
  • 且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构
  • 需满足条件,系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品,系统一次只可能消费其中某一族产品,即同族的产品一起使用

UML 图

结构

依赖关系

实现

创建 Fruit.java

/**
 * @author BNTang
 */
public interface Fruit {
    /**
     * 显示
     */
    void show();
}

创建 AbstractApple.java

/**
 * @author BNTang
 */
public abstract class AbstractApple implements Fruit {

    /**
     * 因为横向x轴的产品等级,有苹果,梨,
     * 但是多了纵向的其他产品族的苹果,梨,
     * 苹果类变为抽象基类,分别去维持多个和苹果相关的产品族对应的产品等级
     */
    @Override
    public abstract void show();
}

创建 AbstractPear.java

/**
 * @author BNTang
 */
public abstract class AbstractPear implements Fruit {
    /**
     * 因为横向x轴的产品等级,有苹果,梨,
     * 但是多了纵向的其他产品族的苹果,梨,
     * 苹果类变为抽象基类,分别去维持多个和苹果相关的产品族对应的产品等级
     */
    @Override
    public abstract void show();
}

创建 ForeignApple.java

/**
 * @author BNTang
 */
public class ForeignApple extends AbstractApple {
    @Override
    public void show() {
        System.out.println("进口苹果");
    }
}

创建 HomeApple.java

/**
 * @author BNTang
 */
public class HomeApple extends AbstractApple {
    @Override
    public void show() {
        System.out.println("国产苹果");
    }
}

创建 HomePear.java

/**
 * @author BNTang
 */
public class HomePear extends AbstractPear {
    @Override
    public void show() {
        System.out.println("国产梨");
    }
}

创建 ForeignPear.java

/**
 * @author 30315
 * @date 2021/07/24
 */
public class ForeignPear extends AbstractPear {
    @Override
    public void show() {
        System.out.println("进口梨");
    }
}

创建 FruitFactory.java 水工工厂

/**
 * @author BNTang
 */
public interface FruitFactory {
    /**
     * 创建苹果
     *
     * @return {@link Fruit}
     */
    Fruit createApple();

    /**
     * 创建梨
     *
     * @return {@link Fruit}
     */
    Fruit createPear();
}

创建 HomeFruitFactory.java

/**
 * @author BNTang
 */
public class HomeFruitFactory implements FruitFactory {
    @Override
    public Fruit createApple() {
        return new HomeApple();
    }

    @Override
    public Fruit createPear() {
        return new HomePear();
    }
}

创建 ForeignFruitFactory.java

/**
 * @author BNTang
 */
public class ForeignFruitFactory implements FruitFactory {
    @Override
    public Fruit createApple() {
        return new ForeignApple();
    }

    @Override
    public Fruit createPear() {
        return new ForeignPear();
    }
}

创建 Client.java

/**
 * @author BNTang
 */
public class Client {
    public static FruitFactory fruitFactory;

    public static void main(String[] args) {
        // 获得某一个产品族
        fruitFactory = new HomeFruitFactory();

        // 获得该产品族下的产品等级
        Fruit homeApple = fruitFactory.createApple();
        homeApple.show();
        Fruit homePear = fruitFactory.createPear();
        homePear.show();

        fruitFactory = new ForeignFruitFactory();
        Fruit foreignApple = fruitFactory.createApple();
        foreignApple.show();

        Fruit foreignPear = fruitFactory.createPear();
        foreignPear.show();
    }
}

角色

抽象工厂(Abstract Factory)

  • 提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品

具体工厂(Concrete Factory)

  • 主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建

抽象产品(Product)

  • 定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品

具体产品(ConcreteProduct)

  • 实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系

抽象工厂模式的优缺点

优点

🐤分离接口和实现

  • 客户端使用抽象来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已
  • 也就是说,客户端从具体的产品实现中解耦

🐱‍💻使切换产品族变得容易

  • 因一个具体的工厂实现代表的是一个产品族,切换产品族只需要切换一下具体工厂

缺点

  • 不太容易扩展新的产品
  • 如需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂(增加新的接口方法)
  • 这样就会导致修改所有的工厂实现类

使用场景

  • 系统独立于产品的创建、组成以及表示
  • 系统配置成具有多个产品的系列,例如 Microsoft Windows 或 Apple McIntosh 类
  • 相关产品对象系列是共同使用的,而且必须确保这一点。这是该模式的关键,否则可以使用 Factory Method 模式
  • 你希望提供产品的类库,只开放其接口,而不是其实现

源码分析

JDK Connection 源码

  • Connection 是一个经典的抽象工厂,而 Statement、PreparedStatement、CallableStatement 是 Connection 这个抽象工厂中提供的三个抽象产品

Mybatis SqlSessionFactory 源码

总结

  • 不同条件下创建不同实例
  • 产品标准化,生产更高效
  • 目的:封装创建细节
posted @ 2021-07-23 23:03  BNTang  阅读(138)  评论(0编辑  收藏  举报