工厂设计模式(Factory Pattern):工厂方法与抽象工厂的实例演示

工厂模式(Factory Pattern)是面向对象编程中最经典、也是最常用的创建型设计模式之一。

简单来说,工厂模式的核心思想就是:将"创建对象"的过程封装起来。对象的使用方不需要知道对象具体是如何被 new 出来的,只需要告诉"工厂"自己需要什么,工厂就会把做好的对象交给你。

之所以这么做,最主要就是解决了对象使用方和创建对象的耦合,在代码层面,客户端无需直接使用 new,对象的创建由工厂负责。否则,当需要使用到一个对象时,自己去 new,就需要考虑到创建这个对象的各种细节,例如构造参数等。

工厂模式有三种:

  1. 简单工厂模式
  2. 工厂方法模式
  3. 抽象工厂模式

首先,既然是工厂模式,那我们先把要生产的产品定义出来,以便后面演示:

java 复制代码
// 定义产品接口
interface Product {     
    void getName();
}

class XiaomiComputer implements Product {
    @Override
    public void getName() {
        System.out.println("小米电脑");
    }
}

class ApplePhone implements Product {
    @Override
    public void getName() {
        System.out.println("苹果手机");
    }
}

工厂模式本质是封装对象创建,客户端只依赖 抽象产品(接口或抽象类) 而不依赖具体类。因此必须有一个抽象产品,工厂方法或抽象工厂才有意义,因此我们定义了 Product 这个接口。

另外,工厂模式是对"创建行为"的设计规范,产品接口的设计由你的业务需求决定,你只需要有个抽象产品接口用于工厂的返回。

简单工厂模式(Simple Factory)

简单工厂模式有时也叫静态工厂模式,但它并不能算是一个正式的设计模式,只是一种常用的对象创建方式(其实就是一个方法)。在简单工厂模式中,通常会有一个工厂类,它根据参数的不同返回不同类型的对象。

使用简单工厂模式甚至都不用定义工厂的接口,直接创建一个实现类即可,你其实就可以将这个简单工厂理解为一个 switch 方法而已:

java 复制代码
class SimpleFactory {
    public static Product createProduct(String type) {
        switch (type) {
            case "小米电脑": return new XiaomiComputer();
            case "苹果手机": return new ApplePhone();
            default: return null;
        }
    }
}

对于产品的使用者来说,需要什么产品仅仅需要传入对应的参数即可:

java 复制代码
class Customer {
    public static void main(String[] args) {
        SimpleFactory.createProduct("小米电脑").getName();
        SimpleFactory.createProduct("苹果手机").getName();
    }
}

可以看出简单工厂模式的优点是简单,对于产品的创建其实就是一个 switch 方法,不过这显然就违背了开闭原则(对于扩展开放,对于修改关闭)。因为要添加新的产品,就需要修改这个 switch 方法,添加新 case ,这违背了开闭原则中"对修改关闭"的理念。

因此这就引出了工厂方法模式。

工厂方法模式(Factory Method)

工厂方法模式定义了一个工厂接口,对于每个产品,都会有一个工厂接口的实现类来负责创建。这样就避免了简单工厂模式的扩展问题:

java 复制代码
// 工厂方法模式的工厂接口
interface Factory {
    Product createProduct();
}

// 小米电脑工厂
class XiaomiComputerFactory implements Factory {
    @Override
    public Product createProduct() { return new XiaomiComputer(); }
}

// 苹果手机工厂
class ApplePhoneFactory implements Factory {
    @Override
    public Product createProduct() { return new ApplePhone(); }
}

当产品使用者需要用到某个产品时,需要先创建对应的工厂,然后用工厂来创建对应的产品:

java 复制代码
class Customer {
    public static void main(String[] args) {
        Factory xiaomiComputerFactory = new XiaomiComputerFactory();
        Product xiaomiComputer = xiaomiComputerFactory.createProduct();
        xiaomiComputer.getName();

        Factory applePhoneFactory = new ApplePhoneFactory();
        Product applePhone = applePhoneFactory.createProduct();
        applePhone.getName();
    }
}

从代码里可见,工厂方法模式在增加新产品时无需修改现有工厂,只需要增加一个新的工厂类而已,已有工厂无需修改,符合开闭原则。 不过它也带来了一个缺点:类数量增多,每增加一种产品就需要增加一个工厂类。

这就引出了工厂模式的最终形态------可以生产"产品家族"的抽象工厂模式。

抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式(Abstract Factory Pattern)是工厂模式的进一步升级,用来创建一系列相关或相互依赖的对象,而无需指定它们的具体类。

简单的说,工厂方法中,每一个工厂只能创建一个产品,而在抽象工厂中,每个工厂能创建一系列相关的产品。

为了演示抽象工厂模式,我们新增小米手机和苹果电脑产品:

java 复制代码
class XiaomiPhone implements Product {
    @Override
    public void getName() {
        System.out.println("小米手机");
    }
}

class AppleComputer implements Product {
    @Override
    public void getName() {
        System.out.println("苹果电脑");
    }
}

由于每个工厂可以生产多个产品,因此需要更改工厂接口的定义和实现:

java 复制代码
// 抽象工厂模式的工厂接口
interface AbstractFactory {
    Product createPhone();
    Product createComputer();
}

class XiaomiFactory implements AbstractFactory {
    @Override
    public Product createPhone() { return new XiaomiPhone(); }
    @Override
    public Product createComputer() { return new XiaomiComputer(); }
}

class AppleFactory implements AbstractFactory {
    @Override
    public Product createPhone() { return new ApplePhone(); }
    @Override
    public Product createComputer() { return new AppleComputer(); }
}

这里的工厂接口 AbstractFactory 只返回 Product 类型,有些时候抽象工厂接口针对不同的产品返回不同的接口类型,不过这并不是工厂模式的要求。抽象工厂模式要求产品使用方依赖抽象,而不是具体产品类,接口设计可以根据实际业务灵活选择,不必强制拆分。可以返回统一接口,也可以返回不同的产品接口,选择哪种方式取决于业务需求和产品操作差异。

这里,产品使用方可以使用如下代码使用工厂创建需要的产品:

java 复制代码
class Customer {
    public static void main(String[] args) {
        AbstractFactory xiaomiFactory = new XiaomiFactory();
        Product xiaomiPhone = xiaomiFactory.createPhone();
        xiaomiPhone.getName();

        AbstractFactory appleFactory = new AppleFactory();
        Product applePhone = appleFactory.createPhone();
        applePhone.getName();
    }
}

从以上例子可以看出抽象工厂的特点:一个工厂创建一系列产品,且增加一个新的工厂比较容易(例如这里增加一个魅族工厂),但如果产品族中新增了一个产品类型,那所有的工厂就都得修改代码了。

总结

  • 简单工厂模式:适合产品少、变化不频繁,使用方便,但违背开闭原则。
  • 工厂方法模式:适合单个产品扩展,增加新产品无需修改已有工厂,但工厂类数量会增加。
  • 抽象工厂模式:适合创建一系列相关产品,保证产品族一致性,增加产品族方便,但新增产品类型时需修改所有工厂。

选择模式时,可根据产品数量、产品族关系以及扩展需求选择最合适的方案。

相关推荐
Giggle12181 小时前
上门家政服务平台 | 多端协同,源码交付,用户端小程序+H5、服务端APP、管理后台
java·小程序·架构·产品运营·个人开发
myloveasuka1 小时前
通配符 “?“
java
码农翻身1 小时前
设计模式,1994年生,2034卒
设计模式
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第41题】【JVM篇】第1题:JVM由哪些部分组成?
java·开发语言·jvm·后端·面试
0xDevNull1 小时前
ConcurrentHashMap 与 Hashtable 深度对比
java·开发语言
happymaker06261 小时前
Spring学习日记——Day01(简单配置使用Spring,手写Spring的简单工厂模式)
java·学习·spring
木易 士心1 小时前
深度解析:一个 Java 对象究竟占用多少字节?
java·开发语言·后端
夜猫子ing1 小时前
《嵌入式 Linux 控制服务从零搭建(二):从目录结构到 CMakeLists,搭一个像样的 C++ 工程骨架》
java·前端·c++
人道领域2 小时前
【LeetCode刷题日记】二叉树翻转:递归与迭代全解析
java·算法·leetcode