设计模式之抽象工厂

文章目录

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

四、总结

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

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

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

相关推荐
网安INF10 分钟前
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
java·web安全·网络安全·flink·漏洞
一叶知秋哈10 分钟前
Java应用Flink CDC监听MySQL数据变动内容输出到控制台
java·mysql·flink
jackson凌16 分钟前
【Java学习笔记】SringBuffer类(重点)
java·笔记·学习
sclibingqing21 分钟前
SpringBoot项目接口集中测试方法及实现
java·spring boot·后端
程序员JerrySUN25 分钟前
全面理解 Linux 内核性能问题:分类、实战与调优策略
java·linux·运维·服务器·单片机
糯米导航29 分钟前
Java毕业设计:办公自动化系统的设计与实现
java·开发语言·课程设计
糯米导航32 分钟前
Java毕业设计:WML信息查询与后端信息发布系统开发
java·开发语言·课程设计
米粉03051 小时前
深入剖析Nginx:从入门到高并发架构实战
java·运维·nginx·架构
简诚1 小时前
HttpURLConnection实现
java
蔡蓝1 小时前
设计模式-建造者模式
服务器·设计模式·建造者模式