设计模式之抽象工厂

文章目录

  • 一、介绍
  • 二、基本组件
  • 三、演示案例
    • [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() 中,我们可以再次结合单例模式来避免频繁实例化婚庆公司对象。

四、总结

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

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

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

相关推荐
Coder码匠44 分钟前
Dockerfile 优化实践:从 400MB 到 80MB
java·spring boot
reddingtons8 小时前
【游戏宣发】PS “生成式扩展”流,30秒无损适配全渠道KV
游戏·设计模式·新媒体运营·prompt·aigc·教育电商·游戏美术
李慕婉学姐8 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆10 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin10 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model200510 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉10 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国11 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_9418824811 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈11 小时前
两天开发完成智能体平台
java·spring·go