工厂模式(Factory Pattern) 与抽象工厂模式(Abstract Factory Pattern)

news2024/9/20 18:50:23

工厂模式(Factory Pattern) 与抽象工厂模式(Abstract Factory Pattern)

工厂模式属于构造型模式,是项目中最常用到的一种设计模式。它的主要作用是提供一种简单的创建对象的方式,使用者无需知道创建实例的细节以及需要哪些资源,只要告诉工厂类指定名字即可,工厂类会在内部创建好该实例后返回给使用者。


工厂模式的使用


​ 假设:现在程序中存在皮鞋、拖鞋、跑鞋三种鞋子,当我想得到一个鞋子对象时,需要进行设置鞋码,染色等过程。但是我在创建对象时,不希望通过很复杂的过程来 `new` 出来一个对象,我只想通过指定的鞋子类型就能得到一个创建好的鞋子对象,这个时候就需要一个工厂类来帮我创建一双鞋子对象了,所有的创建过程都在工厂类中实现,而我只需要调用工厂类的静态获取方法就能得到一个创建好的鞋子对象。

工厂模式类图

image-20221117195604030



实现方法


第一步,创建鞋子的抽象父类

package 工厂模式.实体;

public abstract class{

    public Integer 鞋码;
    public String 颜色;

    public() {
    }

    public void 设置鞋码(Integer 鞋码) {
        System.out.println("鞋子大小设置成功!");
        this.鞋码 = 鞋码;
    }

    public void 染色(String 颜色) {
        this.颜色 = 颜色;
        System.out.println("鞋子染色成功!");
    }

    public abstract void 属性();
}


第二步,创建三种鞋子类

皮鞋

package 工厂模式.实体;

public class 皮鞋 extends{
    public 皮鞋(){
        System.out.println("开始生产一双皮鞋……");
    }
    @Override
    public void 属性() {
        System.out.println("这是一双打工时穿的皮鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
    }
}

拖鞋

package 工厂模式.实体;

public class 拖鞋 extends{

    public 拖鞋(){
        System.out.println("开始生产一双拖鞋……");
    }

    @Override
    public void 属性() {
        System.out.println("这是一双收租的时候穿的拖鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
    }
}

跑鞋

package 工厂模式.实体;

public class 跑鞋 extends{
    public 跑鞋(){
        System.out.println("开始生产一双跑鞋……");
    }
    @Override
    public void 属性() {
        System.out.println("这是一双跑步时穿的跑鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
    }
}


第三步,创建工厂类

工厂类

package 工厂模式;

import 工厂模式.实体.拖鞋;
import 工厂模式.实体.皮鞋;
import 工厂模式.实体.跑鞋;
import 工厂模式.实体.;

public class 工厂类 {

    public static 鞋 获取一双鞋(String 鞋子类别名){
        鞋 一双鞋子 = null;
        // 通过使用者传来的字符串来判断工厂创建什么鞋子
        switch (鞋子类别名){
            case "皮鞋":
                一双鞋子 = new 皮鞋();
                break;
            case "拖鞋":
                一双鞋子 = new 拖鞋();
                break;
            case "跑鞋":
                一双鞋子 = new 跑鞋();
                break;
        }
        // 反正用户没指定什么鞋码和颜色,默认设置下鞋码与颜色
        if (一双鞋子 != null){
            一双鞋子.设置鞋码(42);
            一双鞋子.染色("黑色");
        }
        // 工厂返回创建好的鞋子
        return 一双鞋子;
    }
}


第四步,创建测试类测试

测试类

package 工厂模式;

import 工厂模式.实体.;

public class 测试类{
    public static void main(String[] args) {
        // 我想要一双皮鞋,于是通过工厂类获得皮鞋类的对象
        鞋 皮鞋 = 工厂类.获取一双鞋("皮鞋");
        皮鞋.属性();
        // 我想要一双拖鞋,于是通过工厂类获得拖鞋类的对象
        鞋 拖鞋 = 工厂类.获取一双鞋("拖鞋");
        拖鞋.属性();
        // 我想要一双跑鞋,于是通过工厂类获得跑鞋类的对象
        鞋 跑鞋 = 工厂类.获取一双鞋("跑鞋");
        跑鞋.属性();
    }
}

测试结果

image-20221117194805972




抽象工厂模式的使用


​ 当工厂管理的类很少的时候,那么使用简单的工厂模式就可以了,因为一个工厂类即可完成所有工作。但是,当存在很多个类的创建需要受管理时,那么还使用一个工厂类就很臃肿了。

​ 为解决一个工厂类过于臃肿的问题,我决定把多个类按它们的客观关联关系分配给多个工厂类来管理,而这些新的工厂类,我又要创建一个超级工厂类来管理这些工厂,并且为了方便超级工厂管理这些工厂类,这些工厂类需要继承一个抽象工厂类,从而使超级工厂操作他们的抽象类,而非具体类,符合依赖倒置原则。

​ 假设:除了上文的鞋子,我现在还需要工厂管理卫衣、衬衫、毛衣,很明显他们都继承于衣服类,与鞋子不搭边。于是我不再用一个工厂管理他们,而是使用为鞋子工厂类和衣服工厂类分别管理,同时这些工厂类我也需要一个超级工厂来管理、


抽象工厂模式类图

image-20221117210215226


实现方法


第一步,创建鞋子和衣服的抽象父类

package 设计模式.抽象工厂模式.实体;

public abstract class{

    public Integer 鞋码;
    public String 颜色;


    public void 设置鞋码(Integer 鞋码) {
        System.out.println("鞋子大小设置成功!");
        this.鞋码 = 鞋码;
    }

    public void 染色(String 颜色) {
        this.颜色 = 颜色;
        System.out.println("鞋子染色成功!");
    }

    public abstract void 属性();
}

衣服

package 设计模式.抽象工厂模式.实体;

public abstract class 衣服 {
    public Integer 尺码;
    public String 颜色;

    public void 设置衣服大小(Integer 尺码) {
        System.out.println("衣服大小裁剪成功!");
        this.尺码 = 尺码;
    }

    public void 染色(String 颜色) {
        this.颜色 = 颜色;
        System.out.println("衣服染色成功!");
    }

    public abstract void 属性();
}


第二步,创建三种鞋子类和三种衣服类

皮鞋

package 设计模式.抽象工厂模式.实体;

public class 皮鞋 extends{
    public 皮鞋(){
        System.out.println("开始生产一双皮鞋……");
    }
    @Override
    public void 属性() {
        System.out.println("这是一双打工时穿的皮鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
    }
}

跑鞋

package 设计模式.抽象工厂模式.实体;

public class 跑鞋 extends{
    public 跑鞋(){
        System.out.println("开始生产一双跑鞋……");
    }
    @Override
    public void 属性() {
        System.out.println("这是一双跑步时穿的跑鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
    }
}

拖鞋

package 设计模式.抽象工厂模式.实体;

public class 拖鞋 extends{

    public 拖鞋(){
        System.out.println("开始生产一双拖鞋……");
    }

    @Override
    public void 属性() {
        System.out.println("这是一双收租的时候穿的拖鞋,鞋码为"+this.鞋码+",颜色为"+this.颜色);
    }
}

卫衣

package 设计模式.抽象工厂模式.实体;

public class 卫衣 extends 衣服{

    public 卫衣() {
        System.out.println("正在制作衣服……");
    }

    @Override
    public void 属性() {
        System.out.println("这是一件卫衣,尺码为"+this.尺码+",颜色为"+this.颜色);
    }
}

衬衫

package 设计模式.抽象工厂模式.实体;

public class 衬衫 extends 衣服{

    public 衬衫() {
        System.out.println("正在制作衣服……");
    }

    @Override
    public void 属性() {
        System.out.println("这是一件衬衫,尺码为"+this.尺码+",颜色为"+this.颜色);
    }
}

毛衣

package 设计模式.抽象工厂模式.实体;

public class 毛衣 extends 衣服{

    public 毛衣() {
        System.out.println("正在制作衣服……");
    }

    @Override
    public void 属性() {
        System.out.println("这是一件毛衣,尺码为"+this.尺码+",颜色为"+this.颜色);
    }
}

第三步,创建具体工厂的抽象父类

抽象工厂

package 设计模式.抽象工厂模式.工厂;

import 设计模式.抽象工厂模式.实体.*;

public abstract class 抽象工厂 {
    public abstract 鞋 获取一双鞋(String 鞋子类别名);
    public abstract 衣服 获取一件衣服(String 衣服类别名);
}

第四步,创建鞋子工厂类和衣服工厂类

鞋子工厂

package 设计模式.抽象工厂模式.工厂;

import 设计模式.抽象工厂模式.实体.拖鞋;
import 设计模式.抽象工厂模式.实体.皮鞋;
import 设计模式.抽象工厂模式.实体.跑鞋;
import 设计模式.抽象工厂模式.实体.衣服;
import 设计模式.抽象工厂模式.实体.;

public class 鞋子工厂 extends 抽象工厂 {
    @Override
    public 鞋 获取一双鞋(String 鞋子类别名) {
        鞋 一双鞋子 = null;
        // 通过使用者传来的字符串来判断工厂创建什么鞋子
        switch (鞋子类别名){
            case "皮鞋":
                一双鞋子 = new 皮鞋();
                break;
            case "拖鞋":
                一双鞋子 = new 拖鞋();
                break;
            case "跑鞋":
                一双鞋子 = new 跑鞋();
                break;
        }
        // 反正用户没指定什么鞋码和颜色,默认设置下鞋码与颜色
        if (一双鞋子 != null){
            一双鞋子.设置鞋码(42);
            一双鞋子.染色("黑色");
        }
        // 工厂返回创建好的鞋子
        return 一双鞋子;
    }

    @Override
    public 衣服 获取一件衣服(String 衣服类别名) {
        return null;
    }
}

衣服工厂

package 设计模式.抽象工厂模式.工厂;

import 设计模式.抽象工厂模式.实体.*;

public class 衣服工厂 extends 抽象工厂 {
    @Override
    public 鞋 获取一双鞋(String 鞋子类别名) {
        return null;
    }

    @Override
    public 衣服 获取一件衣服(String 衣服类别名) {
        衣服 一件衣服 = null;
        // 通过使用者传来的字符串来判断工厂创建什么衣服
        switch (衣服类别名){
            case "卫衣":
                一件衣服 = new 卫衣();
                break;
            case "衬衫":
                一件衣服 = new 衬衫();
                break;
            case "毛衣":
                一件衣服 = new 毛衣();
                break;
        }
        // 默认设置下衣服大小与颜色
        if (一件衣服 != null){
            一件衣服.设置衣服大小(42);
            一件衣服.染色("黑色");
        }
        // 工厂返回创建好的衣服
        return 一件衣服;
    }
}

第五步,创建超级工厂类

超级工厂类

package 设计模式.抽象工厂模式;

import 设计模式.抽象工厂模式.实体.拖鞋;
import 设计模式.抽象工厂模式.实体.皮鞋;
import 设计模式.抽象工厂模式.实体.跑鞋;
import 设计模式.抽象工厂模式.实体.;
import 设计模式.抽象工厂模式.工厂.抽象工厂;
import 设计模式.抽象工厂模式.工厂.衣服工厂;
import 设计模式.抽象工厂模式.工厂.鞋子工厂;

public class 超级工厂类 {

    public static 抽象工厂 获取指定工厂(String 工厂类别名){
        抽象工厂 工厂 = null;
        // 通过使用者传来的字符串来判断创建一个什么样的产品工厂
        switch (工厂类别名){
            case "xzgc":
                工厂 = new 鞋子工厂();
                break;
            case "yfgc":
                工厂 = new 衣服工厂();
                break;
        }
        // 超级工厂返回创建好的产品工厂
        return 工厂;
    }
}

第六步,创建测试类测试

测试类

package 设计模式.抽象工厂模式;

import 设计模式.抽象工厂模式.实体.衣服;
import 设计模式.抽象工厂模式.实体.;
import 设计模式.抽象工厂模式.工厂.抽象工厂;

public class 测试类{
    public static void main(String[] args) {
        // 通过超级工厂获得制作衣服的衣服工厂,yfgc是我自己指定的衣服工厂的类别名
        抽象工厂 衣服工厂 = 超级工厂类.获取指定工厂("yfgc");
        衣服 卫衣 = 衣服工厂.获取一件衣服("卫衣");
        卫衣.属性();
        衣服 衬衫 = 衣服工厂.获取一件衣服("衬衫");
        衬衫.属性();
        衣服 毛衣 = 衣服工厂.获取一件衣服("毛衣");
        毛衣.属性();

        System.out.println("————————————————————————————————————");
        // 通过超级工厂获得制作鞋子的鞋子工厂,xzgc是我自己指定的鞋子工厂的类别名
        抽象工厂 鞋子工厂 = 超级工厂类.获取指定工厂("xzgc");
        // 我想要一双皮鞋,于是通过工厂类获得皮鞋类的对象
        鞋 皮鞋 = 鞋子工厂.获取一双鞋("皮鞋");
        皮鞋.属性();
        // 我想要一双拖鞋,于是通过工厂类获得拖鞋类的对象
        鞋 拖鞋 = 鞋子工厂.获取一双鞋("拖鞋");
        拖鞋.属性();
        // 我想要一双跑鞋,于是通过工厂类获得跑鞋类的对象
        鞋 跑鞋 = 鞋子工厂.获取一双鞋("跑鞋");
        跑鞋.属性();
    }
}

测试结果

image-20221117211035989

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13295.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重启虚拟机启动Docker常见问题

文章目录重启虚拟机启动Docker常见问题一、Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?二、admin is not in the sudoers file. This incident will be reported.(没有这个问题请自觉跳过)三、…

华清远见11.17

1.在用户空间中有个字符数组,要求在内核空间打印,用dmesg查看。(ioctl实现) zy.h,封装一个发送用的命令码 #ifndef __LED_H__ #define __LED_H__ #define UACCESS_BUF _IOW(a,1,char [128]) #endif zy.c 申请并自动创…

2022 开源之夏|EMQ 三大开源项目开发圆满收官

今年暑假,EMQ 携手开源之夏,与高校学生开展了一场精彩纷呈的开源之旅。开源之夏(OSPP)是由中科院软件所「开源软件供应链点亮计划」发起的、面向高校学生的暑期开源活动,旨在鼓励在校学生积极参与开源软件的开发维护&a…

CE-Net: Context Encoder Network for 2D MedicalImage Segmentation

Title:用于二维医学图像分割的上下文编码器网络 摘要:在医学图像分割领域中,基于UNet已经成为主流的应用框架。但是在UNet结构中连续的池化和跨步卷积操作会导致一些空间信息的丢失。在本文中提出了一个上下文编码器网络(简称为CE-Net&#…

数据分析师的Windows装机必备软件

文章目录1. Python安装包列表2. Office 3653. Visual Studio Code4. Git5. 向日葵6. 聊天软件7. OneDrive8. iCloud9. 网易邮箱大师10. 搜狗输入法11. 阿里云盘对于数据分析师,装机是再经常不过的一件事情,但是每次装机都要想装什么好,找来找去,故列出来供大家参考. 当然, 系统…

CentOS7自有服务和软件包

文章目录什么是服务管理服务的命令:systemctl列出服务服务启停开机自动启动服务服务状态软件包RPM查询安装了什么软件卸载某个软件安装某个软件查询文件所属的包名查询软件安装后,生成了哪些文件YUM命令epel-release什么是服务 什么是程序(C…

最优化——凸优化概述

引言 这是中科大最优化理论的笔记,中科大凌青老师的凸优化课程,详尽易懂,基础扎实。不论是初学者还是从业多年的人,都值得系统地好好学一遍。 本文主要介绍什么是凸优化,通过几个例子来阐述什么是凸优化问题。让大家…

3年测试经验,面试27k自动化测试岗被diss,想给进阶自动化的人提个醒...

毕业后一直从事功能测试的工作,时间久了就没有一点想法,天天都是点点点,也没有一点提升,看着身边一个个的人都忙得不可开交,打听之后知道他们都是在技术上忙,而不像我,在杂事上忙,特…

vue 使用screenfull 实现全屏展示,全局水印实现, 以及全屏放大后部分组件无法使用,水印无法全屏显示问题的解决

需求:1. web项目中看板页面需要单独全屏显示 2. 项目全局增加水印,水印文字为当前用户登录姓名,登录页不显示水印 出现问题描述 单页面进行全屏显示,下拉,时间选择器,抽屉等组件被 全屏覆盖到下一层&…

MyBatis入门基础

目录 1.什么是MyBatis 2.第一个MyBatis查询 2.1 准备工作 2.2 实际操作 2.2.1 定义接口 2.2.2 创建XML实现上述接口 2.3 单元测试 2.3.1 单元测试的优势 2.3.2 创建并使用单元测试 2.3.3 有关断言 3.增删改的基本操作 3.1 插入操作 特殊的添加:返…

【PyTorch】Torchvision

文章目录三、Torchvision1、Dataset2、DataLoader2.1 test_data2.2 test_loader2.3 drop_last2.4 shuffle三、Torchvision PyTorch官网:https://pytorch.org 1、Dataset 数据集描述:https://www.cs.toronto.edu/~kriz/cifar.html 数据集使用说明&#…

SpringCloud案例day05

SpringCloud Gateway网关 案例1&#xff1a;环境搭建 可以复制 Service-A9001 改成Gateway-C9009 》1&#xff1a;创建工程导入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artif…

汽车全景视频制作让企业营销传播无界长久

全景视频制作 全景VR视频&#xff0c;顾名思义就是能够使我们看到拍摄点周围360景致的视频。传统视频拍摄受限于镜头视角&#xff0c;所以我们只能看到镜头前方180内的景物。而全景VR视频能够看到周围360以及上下180各个角度的一切景物&#xff0c;用户能够更加多方位的观赏视频…

可观测性-Event-指标事件采样策略总结

文章目录前言采样的几种策略简单随机采样周期性完整采样基于条件的采样前言 在默认情况下&#xff0c;系统会采集所有追踪&#xff08;Tracing&#xff09;的数据。但是如果系统比较复杂&#xff0c;采集的端点比较多的时候&#xff0c;对存储压力比较大&#xff0c;这个时候我…

Educational Codeforces Round 135 (Rated for Div. 2)

A:思维 题意&#xff1a;箱子里有N个颜色的球&#xff08;用下标代表不同的颜色&#xff09;&#xff0c;每个颜色的球对应一定的数量&#xff0c;你会进行多次拿球的操作&#xff0c;当箱子里的球颜色一致时&#xff0c;你就不能再拿球了&#xff0c;问最后颜色一致的球是哪个…

免疫抑制作用的转录抑制分子

科研人员发现&#xff1a;社交失败导致了小鼠焦虑行为&#xff0c;进而抑制了化疗药物的治疗过程&#xff0c;加速了肿瘤的发展。在正常小鼠中&#xff0c;人为给予外源性糖皮质激素会使得 Tsc22d3(一个具有很强免疫抑制作用的转录抑制分子)在肿瘤浸润树突细胞(TIDC)的表达上调…

Q3营收同比翻三倍,踩猛“油门”零跑必将领跑?

近日&#xff0c;零跑汽车公布三季度财报。从财报成绩来看&#xff0c;有喜有忧。喜的是销量营收同比环比均出现大幅度增长&#xff0c;忧的是亏损同比扩大86.11%。 营收同比猛增398.5%&#xff0c;销量能否穿越迷雾&#xff1f; 详细来看&#xff0c;三季度零跑汽车销量3.56万…

【附源码】计算机毕业设计JAVA旅行指南网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

HOOPS学习笔记

Hoops简介 HOOPS Visualize由一套集成的组件组成&#xff0c;可快速开发高性能设计、可视化和工程应用程序。HOOPS 3DF在每个组件中保持平台独立性&#xff0c;在Windows、Linux和Mac OS X上提供跨平台解决方案。 HOOPS Visualize包含如下组件&#xff1a; 1.HOOPS/3dGS - HO…

vue+express+mysql+elementUI实现前后端交互增删改查

简介&#xff1a;使用 Vue koa koa2-router mySql elementUI实现前后端交互 页面整体效果图&#xff1a; 编辑页面&#xff1a; 添加页面&#xff1a; 删除操作&#xff1a; 数据库客户端使用Navicat for mysql 当然你需要下载安装 在数据库新建 stuInfo 表和表结构 st…