设计模式之抽象工厂

文章目录

  • 一、介绍
  • 二、基本组件
  • 三、演示案例
    • [1. 定义抽象工厂](#1. 定义抽象工厂)
    • [2. 定义抽象产品](#2. 定义抽象产品)
    • [3. 定义具体工厂](#3. 定义具体工厂)
    • [4. 定义具体产品](#4. 定义具体产品)
    • [5. 代码演示](#5. 代码演示)
    • [6. 代码改造](#6. 代码改造)
  • 四、总结

一、介绍

抽象工厂模式(Abstract Factory Pattern)属于创建型设计模式 。用于解决比工厂方法设计模式更加复杂的问题。

复杂到哪里了呢?

我们将抽象工厂模式和工厂模式进行简单的比较,或许可以有更好的理解:

  • 工厂方法设计模式中,指定工厂只能创建对应的单个产品 ,是一对一的关系。
  • 抽象工厂模式中,不仅需要创建产品的工厂,还多了一个创建工厂的工厂(顶级工厂)。当顶级工厂创建一个工厂时,顶级工厂与工厂是一对一的关系(等同于工厂模式),被创建的工厂可以生产多个产品 ,因此顶级工厂与产品之间是一对多的关系。

二、基本组件

在我们使用抽象工厂设计模式时,一般需要以下组件:

  • 抽象工厂
  • 工厂实现
  • 抽象产品
  • 产品实现

一般来讲,从抽象工厂中获取的对象类型为抽象类型,其具体类型由具体的工厂实现决定。

三、演示案例

唉,到了结婚的年纪了,我们就以结婚为例吧。

1. 定义抽象工厂

结婚是一件十分麻烦的事情,需要准备非常非常多的事情,比如婚车婚房婚纱照等等。所以我们以结婚为工厂,以婚车婚房婚纱照为产品。先对结婚这件事情做一个规范的定义。

java 复制代码
  public interface MarriageFactory {
      /**
       * 产品 - 婚车
       */
      Car getCar();
      /**
       * 产品 - 婚房
       */
      House getHouse();
      /**
       * 产品 - 婚纱照
       */
      Picture getPicture();
  }

2. 定义抽象产品

  • 婚车

    java 复制代码
    public interface Car {
    
        /**
         * 坐婚车
         */
        void drive();
    }
  • 婚房

    java 复制代码
    public interface House {
        /**
         * 买房
         */
        void buyHouse();
    }
  • 婚纱照

    java 复制代码
    public interface Picture {
    
        /**
         * 照相
         */
        void takePicture();
    }

3. 定义具体工厂

我们结婚一般都是要找一个婚庆公司,假设婚庆公司都提供结婚的一条龙服务,包括婚车、婚房、婚纱照等业务,现在我们城里有两家婚庆公司:汤姆婚庆(TomFactory)杰瑞婚庆(JerryFactory)

  • 汤姆婚庆(TomFactory)

    汤姆婚庆公司提供具有汤姆特色的业务,如汤姆婚车(TomCar)汤姆婚房(TomHouse)汤姆照相(TomPicture)

    java 复制代码
    public class TomFactory implements MarriageFactory {
        public TomFactory() {
            System.out.println("选择了汤姆婚庆公司");
        }
        
        @Override
        public Car getCar() {
            return new TomCar();
        }
    
        @Override
        public House getHouse() {
            return new TomHouse();
        }
    
        @Override
        public Picture getPicture() {
            return new TomPicture();
        }
    }
  • 杰瑞婚庆(JerryFactory)

    杰瑞婚庆公司提供具有杰瑞特色的业务,如杰瑞婚车(TomCar)杰瑞婚房(TomHouse)杰瑞照相(TomPicture)

    java 复制代码
    public class JerryFactory implements MarriageFactory {
        public JerryFactory() {
            System.out.println("选择了杰瑞婚庆公司");
        }
        
        @Override
        public Car getCar() {
            return new JerryCar();
        }
    
        @Override
        public House getHouse() {
            return new JerryHouse();
        }
    
        @Override
        public Picture getPicture() {
            return new JerryPicture();
        }
    }

4. 定义具体产品

  • 汤姆婚庆公司提供具有汤姆特色的业务,如汤姆婚车(TomCar)汤姆婚房(TomHouse)汤姆照相(TomPicture)

    java 复制代码
    public class TomCar implements Car{
        /**
         * 婚车
         */
        @Override
        public void drive() {
            System.out.println("汤姆婚车开起来...");
        }
    }
    
    public class TomHouse implements House{
    
        /**
         * 买房
         */
        @Override
        public void buyHouse() {
            System.out.println("汤姆一品房价50w.....");
        }
    }
    
    public class TomPicture implements Picture{
    
        /**
         * 照相
         */
        @Override
        public void takePicture() {
            System.out.println("汤姆照相馆照相.....");
        }
    }
  • 杰瑞婚庆公司提供的业务具有杰瑞特色,如杰瑞婚车(TomCar)杰瑞婚房(TomHouse)杰瑞照相(TomPicture)

    java 复制代码
    public class JerryCar implements Car{
        /**
         * 婚车
         */
        @Override
        public void drive() {
            System.out.println("杰瑞婚车开起来...");
        }
    }
    
    public class JerryHouse implements House{
    
        /**
         * 买房
         */
        @Override
        public void buyHouse() {
            System.out.println("杰瑞一品房价30w...");
        }
    }
    
    public class JerryPicture implements Picture{
    
        /**
         * 照相
         */
        @Override
        public void takePicture() {
            System.out.println("杰瑞照相馆照相.....");
        }
    }

5. 代码演示

下面我们对上述案例进行代码演示

  • 选择杰瑞婚庆公司

    java 复制代码
    public static void main(String[] args) {
    
        // 选择杰瑞婚庆公司
        MarriageFactory factory = new JerryFactory();
        Car car = factory.getCar();
        House house = factory.getHouse();
        Picture picture = factory.getPicture();
    
        car.drive();
        house.buyHouse();
        picture.takePicture();
    }

    输出结果:

  • 选择汤姆婚庆公司

    java 复制代码
    public static void main(String[] args) {
    
        // 选择杰瑞婚庆公司
        MarriageFactory factory = new TomFactory();
        Car car = factory.getCar();
        House house = factory.getHouse();
        Picture picture = factory.getPicture();
    
        car.drive();
        house.buyHouse();
        picture.takePicture();
    }

    输出结果:

6. 代码改造

在上面的测试代码中我们注意到,我们只是对new 婚庆公司的实际类型做了修改,而产品相关代码没有任何改动。于是我们可以将对婚庆公司的实例化过程按照工厂方法设计模式那样转移到工厂中,只需要抽象工厂根据传入的参数返回不同的工厂实例即可。

  • 在抽象工厂中添加静态方法getInstance() 和 枚举类MarriageType

    java 复制代码
    static MarriageFactory getInstance(MarriageType type) {
        if (type.equals(MarriageType.JERRY)) {
            return new JerryFactory();
        }
        return new TomFactory();
    }
    
    enum MarriageType {
        JERRY,
        TOM;
    }
  • 修改测试代码

    java 复制代码
    public static void main(String[] args) {
    
        // 选择杰瑞婚庆公司
        MarriageFactory factory = MarriageFactory.getInstance(MarriageFactory.MarriageType.JERRY);
        Car car = factory.getCar();
        House house = factory.getHouse();
        Picture picture = factory.getPicture();
    
        car.drive();
        house.buyHouse();
        picture.takePicture();
    }

另外,在静态方法getInstance() 中,我们可以再次结合单例模式来避免频繁实例化婚庆公司对象。

四、总结

  • 抽象工厂与工厂方法的最主要区别就是:抽象工厂允许创建多个产品 ;而工厂方法只允许创建一个产品
  • 该设计模式有一个致命缺点:每当我们在工厂中添加新的产品时,工厂的抽象和具体实现都需要修改。当工厂的具体实现较多时,每一个实现都必须适配新添加的产品。

纸上得来终觉浅,绝知此事要躬行。

------------------------我是万万岁,我们下期再见------------------------

相关推荐
落落落sss9 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
我救我自己9 分钟前
UE5运行时创建slate窗口
java·服务器·ue5
2401_8532757329 分钟前
ArrayList 源码分析
java·开发语言
爪哇学长34 分钟前
SQL 注入详解:原理、危害与防范措施
xml·java·数据库·sql·oracle
MoFe11 小时前
【.net core】【sqlsugar】字符串拼接+内容去重
java·开发语言·.netcore
_江南一点雨1 小时前
SpringBoot 3.3.5 试用CRaC,启动速度提升3到10倍
java·spring boot·后端
深情废杨杨1 小时前
后端-实现excel的导出功能(超详细讲解)
java·spring boot·excel
智汇探长1 小时前
EasyExcel自定义设置Excel表格宽高
java·excel·easyexcel
酸奶代码1 小时前
Spring AOP技术
java·后端·spring
代码小鑫2 小时前
A034-基于Spring Boot的供应商管理系统的设计与实现
java·开发语言·spring boot·后端·spring·毕业设计