设计模式之创建型模式---工厂模式

news2024/12/27 10:12:46

文章目录

  • 工厂模式概述
  • 简单工厂
    • 简单工厂的代码实现
    • 简单工厂的使用
    • 简单工厂应用场景
  • 工厂方法
    • 工厂方法模式的代码实现
    • 工厂方法的使用
    • 工厂方法应用场景
  • 抽象工厂
    • 抽象工厂模式代码实现
    • 抽象工厂的使用方法
    • 抽象工厂模式的应用场景
  • 总结

在这里插入图片描述

工厂模式概述

工厂模式从名字就能看出,这种模式是用于创建对象的,因为现实生活中,工厂就是用于生产产品的嘛。所以工厂模式的名字起得非常的贴近生活。工厂模式根据应用场景的不同,分为简单工厂,工厂方法,和抽象工厂三种。现实生活中的工厂有的可以生产几种产品,客户根据工厂提供的产品定制就行。比如生产A,B两种品牌的车。这种情况对应到工厂设计模式中就是简单工厂模式。用户只需要给工厂说我要A或者B品牌的车就行。但是如果用户说我想要C品牌的车,这时就难受了,工厂得需要做改建,增加C品牌产线等工作,非常繁琐,于是就出现了特定的工厂,比如生产A品牌车的工厂,生产B品牌的工厂。但是工厂也不能乱建,必须按照总公司的标准建造。所以这种工厂对应到设计模式中就是工厂方法模式,当用户需要新品牌的车时,直接按照总公司标准建造新的工厂就行,不影响之前的工厂工作。但是这种每新加一个品牌的车就得建一个工厂的方法确实比较奢侈,因为可能没那么多的土地,所以我们就可以让我们的工厂承担更多的任务,比如在造车的同时,咱们还可以造手机。这种工厂对应到设计模式中就是抽象工厂模式。

工厂模式的好处就是客户不需要知道对象的创建过程,只是通过简单的调用就能拿到自己想要的对象,这也是工厂设计模式的初衷,屏蔽复杂的对象构造过程,让调用方能通过简单的接口获取到自己想要的对象。从上面的例子我们也可以得出一个结论,就是根据我们的实际场景选择对应的工厂设计模式。比如就很简单的几个对象,咱们使用简单工厂模式就行。对应到生活中的例子就是,有多少钱,干多少事,本来就只有造两种品牌的车的钱,咱们就不要到处建工厂了。

简单工厂

假如我们要创建的产品不多,只要一个工厂类就可以,这种模式就称为简单工厂模式,比如我们就生产CarA 和CarB两种车,那么直接用一个工厂类就可以了,没有必要花钱建多个工厂。简单工厂的类图如下所示。
在这里插入图片描述
根据类图我们用JAVA实现下这个造车的过程。
注意:例子只是为了方便介绍本文的内容,不具有真实造车的参考价值

简单工厂的代码实现

根据类图,我们首先创建一个接口表示我们要造的所有车具有的行为,比如都需要安装引擎,轮子,刷颜色等行为。

public interface ICar {
    // 粉刷车身的颜色
    void printColor();

    // 安装车的引擎
    void installEngine();

    // 安装车的轮子
    void installWheels();

    // 安装车载操作系统
    void installSystem();
}

然后创建两个产品CarA和CarB,并且都继承实现ICar的接口。

public class CarA implements ICar {
    private String color;
    private String engine;
    private String wheels;
    private String system;
    @Override
    public void printColor() {
        System.out.println("CarA 的颜色是红色");
        color = "RED";
    }

    @Override
    public void installEngine() {
        System.out.println("安装 CarA 的引擎");
        engine = "A-Engine";
    }

    @Override
    public void installWheels() {
        System.out.println("安装 CarA 的轮子");
        wheels = "A牌轮子";
    }

    @Override
    public void installSystem() {
        System.out.println("安装 CarA 的车载系统");
        system = "A OS";
    }

    @Override
    public String toString() {
        return "CarA{" +
                "color='" + color + '\'' +
                ", engine='" + engine + '\'' +
                ", wheels='" + wheels + '\'' +
                ", system='" + system + '\'' +
                '}';
    }
}

public class CarB implements ICar {
    private String color;
    private String engine;
    private String wheels;
    private String system;

    @Override
    public void printColor() {
        System.out.println("CarB 的颜色是蓝色");
        color = "Blue";
    }

    @Override
    public void installEngine() {
        System.out.println("安装 CarB 的引擎");
        engine = "B-Engine";
    }

    @Override
    public void installWheels() {
        System.out.println("安装 CarB 的轮子");
        wheels = "B牌轮子";
    }

    @Override
    public void installSystem() {
        System.out.println("安装 CarB 的车载系统");
        system = "B OS";
    }

    @Override
    public String toString() {
        return "CarB{" +
                "color='" + color + '\'' +
                ", engine='" + engine + '\'' +
                ", wheels='" + wheels + '\'' +
                ", system='" + system + '\'' +
                '}';
    }
}

然后我们新建一个简单工厂类,通过一个buildCar方法构建我们的CarA和CarB两种车的对象

public class SimpleCarFactory {
    public static final String CAR_A = "CAR_A";
    public static final String CAR_B = "CAR_B";
    public static ICar buildCar(String type){
        ICar car = null;
        if(CAR_A.equals(type)){
            car = new CarA();
        }

        if(CAR_B.equals(type)){
            car =  new CarB();
        }
        if(car != null){
            car.printColor();
            car.installEngine();
            car.installWheels();
            car.installSystem();
        }
        return car;
    }
}

简单工厂的使用

我们建立一个Client类演示如何使用简单工厂

public class Client {
    public static void main(String[] args) {
        // 简单工厂
        ICar carA = SimpleCarFactory.buildCar(SimpleCarFactory.CAR_A);
        System.out.println("build a car A: " + carA);

        ICar carB = SimpleCarFactory.buildCar(SimpleCarFactory.CAR_B);
        System.out.println("build a car B: " + carB);
        }

运行结果:
在这里插入图片描述

简单工厂应用场景

对于产品种类相对较少的情况,比如我们做相机开发时,Android的系统相机支持多种种API,Camera1和Camera2以及后面的CameraX,这里我们就可以使用简单工厂模式,去根据具体的应用场景获取对应的CameraA对象。

工厂方法

简单工厂确实简单好用,但是缺点也很明显,每增加一种产品就需要增加一个具体的产品类并且修改工厂类,这违背开闭原则(开闭原则是指我们的程序应该对修改关闭,对扩展开放),就比如我们此时如果要造CarC,但我们只有一个工厂,所以就需要我们去在当前的工厂上修改以保证能够造CarC产品。这时小伙伴可能会说,那么再建一个工厂生产C产品就行了呀。对的,这就是工厂方法模式。工厂方法模式时对简单工厂模式的进一步抽象化。这样做的好处是可以使我们的程序在不修改原来代码的情况下引进新产品。从而满足开闭原则。这里还是以造车为例子。工厂方法的模式类图如下所示
在这里插入图片描述

工厂方法模式的代码实现

这里的ICar接口和对象使用的都是简单工厂部分的,代码一样,就不重复贴了。这里只贴新的代码。我们需要建立一个工厂的接口。定义工厂的功能是生产车,后面建造的工厂都必须以这个为标准,不能乱建。

public interface IFactory {
    ICar buildCar();
}

建立造CarA产品的工厂

public class ACarFactory implements IFactory{
    private ICar mCarA = new CarA();
    @Override
    public ICar buildCar() {
        mCarA.printColor();
        mCarA.installEngine();
        mCarA.installWheels();
        mCarA.installSystem();
        return mCarA;
    }
}

建立造CarB产品的工厂

public class BCarFactory implements IFactory{
    private ICar mCarB = new CarA();
    @Override
    public ICar buildCar() {
        mCarB.printColor();
        mCarB.installEngine();
        mCarB.installWheels();
        mCarB.installSystem();
        return mCarB;
    }
}

这样我们的工厂方法模式就实现了,这时假如我们要新增一个CarC 产品,我们只需要新增一个工厂类和一个产品C的类就可以了,符合开闭原则,代码如下:
新增产品C:

public class CarC implements ICar {
    private String color;
    private String engine;
    private String wheels;
    private String system;

    @Override
    public void printColor() {
        System.out.println("CarC 的颜色是白色");
        color = "White";
    }

    @Override
    public void installEngine() {
        System.out.println("安装 CarC 的引擎");
        engine = "C-Engine";
    }

    @Override
    public void installWheels() {
        System.out.println("安装 CarC 的轮子");
        wheels = "C牌轮子";
    }

    @Override
    public void installSystem() {
        System.out.println("安装 CarC 的车载系统");
        system = "C OS";
    }

    @Override
    public String toString() {
        return "CarC{" +
                "color='" + color + '\'' +
                ", engine='" + engine + '\'' +
                ", wheels='" + wheels + '\'' +
                ", system='" + system + '\'' +
                '}';
    }
}

建造产品C的工厂:

public class CCarFactory implements IFactory{
    private ICar mCarC = new CarC();
    @Override
    public ICar buildCar() {
        mCarC.printColor();
        mCarC.installEngine();
        mCarC.installWheels();
        mCarC.installSystem();
        return mCarC;
    }
}

工厂方法的使用

同样我们新建一个Client类来演示工厂方法的使用

public class Client {
    public static void main(String[] args) {
        // 工厂方法
        IFactory mFactoryA = new ACarFactory();
        ICar mCarA = mFactoryA.buildCar();
        System.out.println("工厂方法模式构建 carA: " + mCarA);

        IFactory mFactoryB = new BCarFactory();
        ICar mCarB = mFactoryB.buildCar();
        System.out.println("工厂方法模式构建 carB: " + mCarB);

        IFactory mFactoryC = new CCarFactory();
        ICar mCarC = mFactoryC.buildCar();
        System.out.println("工厂方法模式构建 mCarC: " + mCarC);
    }
}

运行结果:
在这里插入图片描述

工厂方法应用场景

当我们的同种产品比较多的时候,可以考虑使用工厂方法模式,也就是说你开公司,目前只生产A,B两种产品,这两种产品都是车,只是一些构造的工艺技术有不同而已,但是未来你可能会继续增加你的同种类型的产品,比如生产C车,,这种情况就可以考虑使用工厂方法模式。工厂方法模式可以满足我们扩展新产品而不需要修改以前的工厂和产品。简单说就是:如果你造车,你的工厂就只是造车,生产手机,你的工厂就是只生产手机。工厂模式只考虑生产同种等级的产品,但读者可能会想,假如我一个工厂想造车又想生产手机怎么办呢?那就得用到抽象工厂模式了。

抽象工厂

如前面所说,工厂方法模式只考虑生产同种等级的产品,比如造车的工厂就只是造车,生产手机的工厂就只是生产手机,但是在我们的现实生活中,许多工厂是综合性的工厂,比如造车的工厂也能造手机。为啥这么设计呢?用工厂方法不是更好吗,想造手机,再建一个造手机的工厂不就行了吗?用毛爷爷的话说,理论上行得通,但实际上不可行,因为现在的很多公司都是综合性的公司,大公司会生产各种各样的产品,要是每种产品就建一个工厂,那么地球上的土地就这么点,哪里够用呀,所以综合性工厂可以解决这个问题。这里我们以造车的例子为基础,为工厂新增一个造手机的功能。类图如下:
在这里插入图片描述

抽象工厂模式代码实现

基于工厂方法的例子,我们新增一个产品手机,首先定义手机的公共接口:

public interface IPhone {
    // 刷上颜色
    void printColor();

    // 安装系统
    void installOS();
}

创建手机A

public class PhoneA implements IPhone{
    private String color;
    private String systemOs;
    @Override
    public void printColor() {
        System.out.println("粉刷手机颜色为红色");
        color = "RED";

    }

    @Override
    public void installOS() {
        System.out.println("安装手机的操作系统为Android系统");
        systemOs = "Android";
    }

    @Override
    public String toString() {
        return "PhoneA{" +
                "color='" + color + '\'' +
                ", systemOs='" + systemOs + '\'' +
                '}';
    }
}

创建手机B:

public class PhoneB implements IPhone{
    private String color;
    private String systemOs;
    @Override
    public void printColor() {
        System.out.println("粉刷手机颜色为蓝色");
        color = "BLUE";

    }

    @Override
    public void installOS() {
        System.out.println("安装手机的操作系统为IOS系统");
        systemOs = "IOS";
    }

    @Override
    public String toString() {
        return "PhoneB{" +
                "color='" + color + '\'' +
                ", systemOs='" + systemOs + '\'' +
                '}';
    }
}

然后我们定义我们要建的综合性工厂的标准接口

public interface IAbstractFactory {
    ICar buildCar();
    IPhone buildPhone();
}

新建两个综合性工厂,A和B,分别生产A品牌的产品和B品牌的产品。

// 生产A品牌的产品
public class AFactory implements IAbstractFactory {
    private ICar mCarA =new  CarA();
    private IPhone mPhoneA = new PhoneA();
    @Override
    public ICar buildCar() {
        mCarA.printColor();
        mCarA.installEngine();
        mCarA.installWheels();
        mCarA.installSystem();
        return mCarA;
    }

    @Override
    public IPhone buildPhone() {
        mPhoneA.printColor();
        mPhoneA.installOS();
        return mPhoneA;
    }
}
// 生产B品牌的产品
public class BFactory implements IAbstractFactory {
    private ICar mCarB =new CarB();
    private IPhone mPhoneB = new PhoneB();
    @Override
    public ICar buildCar() {
        mCarB.printColor();
        mCarB.installEngine();
        mCarB.installWheels();
        mCarB.installSystem();
        return mCarB;
    }

    @Override
    public IPhone buildPhone() {
        mPhoneB.printColor();
        mPhoneB.installOS();
        return mPhoneB;
    }
}

抽象工厂的使用方法

我们新建一个Client的类来演示抽象工厂的使用方法

public class Client {
    public static void main(String[] args) {
        // 抽象工厂
        IAbstractFactory mAFactory = new AFactory();
        ICar myAcar = mAFactory.buildCar();
        IPhone myAPhone = mAFactory.buildPhone();
        System.out.println("A工厂造的车: " + myAcar);
        System.out.println("A工厂造的手机: " + myAPhone);

        IAbstractFactory mBFactory = new BFactory();
        ICar myBcar = mBFactory.buildCar();
        IPhone myBPhone = mBFactory.buildPhone();
        System.out.println("B工厂造的车: " + myBcar);
        System.out.println("B工厂造的手机: " + myBPhone);
    }
}

运行结果:
在这里插入图片描述

抽象工厂模式的应用场景

当需要生产多种产品的时候,比如我们的工厂需要造车和造手机时,可以考虑使用抽象工厂模式,比如我们的电器厂,就可以考虑使用抽象工厂模式,因为电器厂既可以生产电视机也能生产空调。,农场也是,农场可以种植物,也可以养动物。

总结

本文主要以造车和手机的例子介绍了工厂模式的三种形式,简单工厂,工厂方法,抽象工厂的实现,并且在每节增加了类图和应用场景。读者可以根据应用场景和类图选择对应的工厂模式应用到自己的项目中,让自己的代码更加优雅和可维护。

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

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

相关文章

【Java笔记】如何创建自己的注解+注解怎么用于反射+SpringBoot常见注解

文章目录 0. 为什么SpringBoot要整这么多注解?1. 一些基础知识1.1 什么是注解1.2 Java内置注解1.2.1 作用在代码上的注解1.2.2 作用在注解的注解(元注解)1.2.3 Java 7之后的新注解 1.3 注解的作用1.4 如何实现一个自己的注解?1.4.…

向量的求导

参考: 向量的求导 向量内积求导

如何提交已暂存的更改到本地仓库?

文章目录 如何提交已暂存的更改到本地Git仓库?步骤1:确认并暂存更改步骤2:提交暂存的更改到本地仓库 如何提交已暂存的更改到本地Git仓库? 在Git版本控制系统中,当你对项目文件进行修改后,首先需要将这些更…

Diffusion Model原理剖析

目录 前言1. DDPM演算法初览2. 图像生成模型共同目标3. VAE: Lower bound of l o g P ( x ) logP(x) logP(x)4. Diffusion Model背后的数学原理5. 为什么需要Sample?6. Diffusion Model的应用7. Diffusion Model成功的关键总结参考 前言 接着上篇文章 图像生成模型浅析&#…

四川古力未来科技抖音小店:科技新宠,购物新选择

在数字化浪潮席卷全球的今天,电商行业日新月异,新兴平台层出不穷。四川古力未来科技抖音小店,作为其中的佼佼者,凭借其独特的魅力和创新的服务模式,正逐渐成为消费者眼中的购物新宠。 一、四川古力未来科技抖音小店的独…

深度卷积神经网络的整体运行流程(以alexnet为例)

0.基础概念(复习一下) 1.小批量随机梯度下降 目的: 希望找到最佳的参数,使损失函数最小。 使损失函数对w求导(b就是x等于1的w),一个小批次的/eta(学习率)*小批次的平均…

2024团体设计天梯赛之L1-101 别再来这么多猫娘了

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话: 知不足而奋进,望远山而前行&am…

上市公司数字化转型速度测-含代码及原始数据(2000-2022年)

数据来源:Wind数据库、企业年报时间跨度:2000-2022年 其中吴非、赵宸宇版本的数据是从2000到2022年;袁淳版本和李瑛玫版本的数据均是从2001-2022年。数据范围:上市公司数据指标:计算了三份测算数字化转型速度的数据。其…

Java中的构造器

即使在类中什么都不写也会自动的生成一个构造器 注意 使用new关键字是在调用构造器 如果定义了有参构造 那么就不会默认的走Person person new Person();如果没有自己手动的定义无参构造就不能使用 在idea中 用按键Altinsert可以快速生成有参、无参构造(某些品牌的…

yolov8-obb旋转目标检测详细流程

一、数据标注 由于旋转目标标注与传统的目标检测标注有一定的区别,故使用roLabelImg或者labelimg2进行标注,以下标注软件选用的是roLabelImg。 roLabelImg下载地址:https://github.com/cgvict/roLabelImg 直接在原有的labelimg环境中使用roL…

宝塔面板国际版aaPanel 精简版安装

宝塔面板国际版aaPanel 精简版安装 很多人都知道宝塔面板,但不知道宝塔面板还有英文版,宝塔面板英文版不是单纯的宝塔面板的翻译,而是根据老外的使用习惯及国外的网络环境做了一定的优化, 比如:去掉了手机号验证、去…

关于淘宝API接口请求数据的靠谱方式,主要包括以下几个方面:

关于淘宝API接口请求数据的靠谱方式,主要包括以下几个方面: 了解API接口和请求方式: API接口采用通用的HTTP协议,支持GET、POST等多种请求方式。GET方法主要用于向指定资源发出请求并返回实体主体内容,如查询、菜单列…

PBR相关基础知识

文章目录 **核心理念****关键组件与参数****工作流程****优势****挑战与注意事项**实例展示 基于物理的渲染(Physically Based Rendering, PBR)是一种现代计算机图形学技术,它致力于通过模拟真实世界中光与物质相互作用的物理规律来生成高度逼…

JAVA学习笔记30(线程)

1.线程 1.线程的概念 1.线程是由进程创建的,是进程的一个实体 2.一个进程可以拥有多个线程 2.并发 ​ *同一时刻,多个任务交替执行,造成一种"貌似同时"的错觉,单核cpu实现的多任务就是并发 3.并行 ​ *同一时刻&…

Python的round与Excel的round不一样?

Python四舍五入怎么做 round()奇进偶舍round函数既不是“四舍五入”的原则,也不是“四舍六入无成双”的原则。 decimal round() 偶然发现python的round函数和excel的round函数对某些数据的处理结果不一致。有看到博主提到是奇进偶舍的方法,但经过验证和…

elementUi 日期选择器 组件禁止手输

添加:editable"false" <el-date-pickerv-model"formInline.EndTime"type"datetime"placeholder"选择结束时间"format"YYYY-MM-DD HH:mm:ss"value-format"YYYY-MM-DD HH:mm:ss":editable"false">&…

0 transformers入门,HuggingFace!

目录 1 了解 2 文本分类 1 了解 1 依赖安装 !pip install transformers -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 2 了解transformers 能做什么 from transformers.pipelines import SUPPORTED_TASKS SUPPORTED_TASKS.items()2 文本分类 我没外网所以…

[2024更新]如何从Android恢复已删除的相机照片?

相信大家都经历过Android手机误删相机图片的经历。您是否正在寻找一种可行的方法来挽救这些丢失的照片&#xff1f;如果这是你迫切想解决的问题&#xff0c;那么这篇文章绝对可以帮助你。然而&#xff0c;与其考虑如何从Android恢复已删除的相机照片&#xff0c;我们更愿意建议…

3D模型人物换装系统(五 模型核批之后模型uv不正确)模型UV不正确

3D模型人物换装系统&#xff08;五 模型核批之后模型uv不正确&#xff09;模型UV不正确 介绍展示Maya导入查看uvUnity中测试分析没合批为什么没有问题总结 介绍 最近在公司里给公司做模型优化合批的时候发现了模型的uv在合批之后无法正常展示&#xff0c;这里找了很多的原因&a…

【竞技宝】中超:泰山队4比1大胜沧州雄狮,费南多独造三球

泰山队在本轮中超主场跟沧州雄狮相遇,这场比赛开打前球迷都觉得主队不好踢。因为,沧州雄狮是中超大黑马,整体战绩可圈可点。另外,泰山队则是境遇不佳,主帅崔康熙饱受球队伤病不断的困扰。最让山东球迷觉得郁闷的是崔康熙上一轮因质疑马宁吹罚,还直接罚到了看台。这就意味着崔康…