[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式

前言:

为什么之前写过Golang 版的设计模式,还在重新写Java 版?

答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。

为什么类图要附上uml

因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那么学习者也只能复制一张图片,可复用性较低,附上uml,方便有新理解时,快速出新图。


🔥[设计模式Java实现附plantuml源码]专链

  1. 确保对象的唯一性~单例模式
  2. 集中式工厂的实现~简单工厂模式
  3. 多态工厂的实现------工厂方法模式
  4. 产品族的创建------抽象工厂模式

文章目录


工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题。但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,可以考虑将一些相关的产品组成一个"产品族",由同一个工厂来统一生产,这就是本章将要学习的抽象工厂模式的基本思想。
为了更好地理解抽象工厂模式,这里先引入如下两个概念:

(1)产品等级结构。产品等级结构即产品的继承结构,例如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

(2)产品族。在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。例如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。

抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。
抽象工厂模式定义如下 :抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。

uml 复制代码
@startuml

abstract class 抽象产品族1海尔{}

class 产品1电视机 extends 抽象产品族1海尔 {}
class 产品2洗衣机 extends 抽象产品族1海尔 {}

abstract class 抽象产品族2{}

abstract class 抽象工厂 {

+ 生产抽象产品族1():抽象产品族1海尔
+ 生产抽象产品族2():抽象产品族2
}

class 具体工厂1 extends 抽象产品族1海尔 implements 抽象工厂 {
+ 生产产品1():抽象产品族1海尔
+ 生产产品2():抽象产品族1海尔
}

具体工厂1 -up-> 产品1电视机
具体工厂1 -up-> 产品2洗衣机

@enduml

在抽象工厂模式结构图中包含以下4个角色。

(1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每个方法对应一种产品。

(2)ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每种产品都位于某个产品等级结构中。

(3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。

(4)ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现在抽象产品接口中声明的业务方法。

代码实现

java 复制代码
public class AbstractFactoryDemo {
    // 抽象产品族1
    static abstract class AbstractProductFamily1 {}

    // 产品1
    static class Product1 extends AbstractProductFamily1 {}

    // 产品2
    static class Product2 extends AbstractProductFamily1 {}

    // 抽象产品族2
    static abstract class AbstractProductFamily2 {}

    // 抽象工厂
    interface AbstractFactory {
        AbstractProductFamily1 createProductFamily1();
        AbstractProductFamily2 createProductFamily2();
    }

    // 具体工厂1
    static class ConcreteFactory1 implements AbstractFactory {
        @Override
        public AbstractProductFamily1 createProductFamily1() {
            return new Product1();
        }

        @Override
        public AbstractProductFamily2 createProductFamily2() {
            // 在具体工厂1中创建抽象产品族2的实例
            return null; // 根据具体情况进行实现
        }
    }


    public static void main(String[] args) {
        // 创建具体工厂1的实例
        AbstractFactory factory = new ConcreteFactory1();

        // 使用具体工厂1创建抽象产品族1的实例
        AbstractProductFamily1 product1 = factory.createProductFamily1();
        AbstractProductFamily1 product2 = factory.createProductFamily1();
        System.out.println(product1);
        System.out.println(product2);

        // 使用具体工厂1创建抽象产品族2的实例
        AbstractProductFamily2 product3 = factory.createProductFamily2();
        System.out.println(product3);

    }

}

抽象工厂总结

抽象工厂模式的主要优点如下:

(1)抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了在抽象工厂中声明的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

(2)当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

(3)增加新的产品族很方便,无须修改已有系统,符合开闭原则。

抽象工厂模式的主要缺点是:

增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则。

适用场景

在以下情况下可以考虑使用抽象工厂模式:

(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。

(2)系统中有多于一个的产品族,而每次只使用其中某一个产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。

(3)属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束。例如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类 型。

(4)产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。

相关推荐
程序媛小果8 分钟前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林13 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨27 分钟前
El表达式和JSTL
java·el
duration~1 小时前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射
九圣残炎3 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode