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

文章目录

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

在这里插入图片描述

工厂模式概述

工厂模式从名字就能看出,这种模式是用于创建对象的,因为现实生活中,工厂就是用于生产产品的嘛。所以工厂模式的名字起得非常的贴近生活。工厂模式根据应用场景的不同,分为简单工厂,工厂方法,和抽象工厂三种。现实生活中的工厂有的可以生产几种产品,客户根据工厂提供的产品定制就行。比如生产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);
    }
}

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

抽象工厂模式的应用场景

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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在【laravel框架】学习中遇到的常见的问题以及解决方法

👨‍💻个人主页:开发者-曼亿点 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 曼亿点 原创 👨‍💻 收录于专栏&#xff1a…

.net core webapi 高颜值的接口管理系统界面取代swagger,更好调试和查看

.net core webapi 高颜值的接口管理系统界面取代swagger,更好调试和查看 安装 dotnet add package IGeekFan.AspNetCore.Knife4jUI --version 0.0.16配置文档: 配置起始页 builder.Services.AddSwaggerGen(c > {// 配置 Swagger 文档相关信息c.Swa…

开源项目实现简单实用的股票回测

1 引言 之前,尝试做股票工具一直想做的大而全,试图抓取长期的各个维度数据,然后统计或者训练模型。想把每个细节做到完美,结果却陷入了细节之中,最后烂尾了。 最近,听到大家分享了一些关于深度学习、时序…

【面试题】MySQL 事务的四大特性说一下?

事务是一个或多个 SQL 语句组成的一个执行单元,这些 SQL 语句要么全部执行成功,要么全部不执行,不会出现部分执行的情况。事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 事务的主要作用是保证数…

Core dump(核心转储)

文章目录 core dump core dump 进程退出时有三种情况正常退出,退出结果不对,异常退出 低7位表示收到信号退出,次低八位代表进程正常退出它的退出码!在第八位有一个core dump标志位,这个标志位表示进程收到信号做的动…

Leetcode 28. 找出字符串中第一个匹配项的下标

心路历程: 两个字符串匹配的问题基本都可以用动态规划解决,递推关系就是依次匹配下去 注意的点: 1、注意边界条件是匹配串needle到头,但是haystack不一定需要到头 2、这道题按照从i开始的字符串而不是从i结束的进行DP建模 解法…

vue---计算属性

姓名案例 1.使用插值语法实现 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>姓名案例_插值语法实现</title><!-- 引入Vue --><script type"text/javascript" src"../js/vue.js"&g…

被这批B端界面的颜值给征服了,匍匐拜倒。。

高颜值的 B 端界面对于企业来说具有非常重要的作用&#xff0c;可以帮助企业提升品牌形象、吸引客户、增加用户留存、提升竞争力、提高交易转化率&#xff0c;以及优化用户体验&#xff0c;从而为企业带来更多的商业机会和利益。本期分享一批&#xff0c;都是颜值杠杠的。

制造业信息安全实践——企业信息安全运营规划

前言 制造业作为一个庞大的传统产业&#xff0c;涵盖了汽车、船舶、飞机、家电、新能源等众多领域。当前&#xff0c;无论是国内还是国外的制造业都面临着一个共同的挑战&#xff1a;在计算机和信息时代的背景下&#xff0c;如何跟上IT技术的发展步伐&#xff1f;如何让传统产…

网络协议安全:OSI七层模型分层及作用,数据封装与解封过程,数据传输过程。

「作者简介」&#xff1a;2022年北京冬奥会中国代表队&#xff0c;CSDN Top100&#xff0c;学习更多干货&#xff0c;请关注专栏《网络安全自学教程》 这一章节我们需要知道OSI分哪七层&#xff0c;每层的作用&#xff0c;知道数据在七层模型中是怎样传输的&#xff0c;封包和解…

【离婚不再难】告别痛苦,用一纸起诉状重新启航

【离婚不再难】告别痛苦&#xff0c;用一纸起诉状重新启航 在这个瞬息万变的时代&#xff0c;婚姻关系的走向已不再是人们心中永恒的定局。当缘尽人散&#xff0c;面对离婚的纷扰&#xff0c;你是否感到迷茫与无助&#xff1f;别担心&#xff0c;李秘书讲写作公众号在这里&…

C++11——线程库的理解与使用

目录 前言 一、线程库的构造 1.默认构造 2.带参构造 3.拷贝构造与赋值拷贝&#xff08;不支持&#xff09; 4.移动构造 二、线程调用lambda函数 三、线程安全与锁 1.lambda中的线程与锁 2.函数指针中的线程与锁 3.trylock() 4.recursive_mutex 5.lock_gurad守卫锁…

​「Python大数据」VOC数据清洗

前言 本文主要介绍通过python实现数据清洗、脚本开发、办公自动化。读取voc数据,存储新清洗后的voc数据数据。 一、业务逻辑 读取voc数据采集的数据批处理,使用jieba进行分词,去除停用词,清洗后的评论存储到新的列中保存清洗后的数据到新的Excel文件中二、具体产出 三、执…

three.js(2):渲染第一个three.js三维对象

这一章渲染一个立方体对象到场景中&#xff0c;效果如下&#xff1a; 代码如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><script text"module" charset"UTF-8"…

LabVIEW学习记录2 - MySQL数据库连接与操作

LabVIEW学习记录2 - MySQL数据库连接与操作 一、前期准备1.1 windows下安装MySQL的ODBC驱动 二、LabVIEW创建MySQL 的UDL文件三、LabVIEW使用UDL文件进行MySQL数据库操作3.1 建立与数据库的连接&#xff1a;DB Tools Open Connection.vi3.2 断开与数据库的连接&#xff1a;DB T…

功能测试前景揭秘:会被淘汰吗?

在当今快速发展的信息时代&#xff0c;软件已经成为我们工作、学习乃至生活中不可或缺的一部分。随着技术的不断进步和应用的广泛普及&#xff0c;软件测试作为保障软件质量和功能实现的关键步骤&#xff0c;其职业发展路径也受到了广泛的关注。特别是针对功能测试这一细分领域…

The layered MVP architecture in Acise

Acise是一款CAx软件开发平台&#xff0c;本文给出Acise中的MVP架构模式的实现思路。 注1&#xff1a;文章内容会不定期更新。 MVP Data Model View Model 参考文献 Erich Gamma. Design Patterns:elements of reusable object-oriented software. Addison Wesley, 1994.Josep…

高达27K star!基于LLM构建本地智能知识库 太猛了

觉得搞一个AI的智能问答知识库很难吗&#xff1f;那是你没有找对方向和工具&#xff0c; 今天我们分享一个开源项目&#xff0c;帮助你快速构建基于Langchain 和LLM 的本地知识库问答&#xff0c;在GitHub已经获得27K star&#xff0c;它就是&#xff1a;Langchain-Chatchat L…

摄影的技术和艺术,摄影师的日常修养

一、资料描述 本套摄影师资料&#xff0c;大小1.50G&#xff0c;共有67个文件。 二、资料目录 《1900&#xff0c;美国摄影师的中国照片日记》.pdf 《40幅引人入胜的获奖照片》.pdf 《把你的照片换成钱&#xff1a;图片库摄影师的生存之道》(美)陈小波.扫描版.PDF 《半小…

OceanBase数据库日常运维快速上手

这里为大家汇总了从租户创建、连接数据库&#xff0c;到数据库的备份、归档、资源配置调整等&#xff0c;在OceanBase数据库日常运维中的操作指南。 创建租户 方法一&#xff1a;通过OCP 创建 确认可分配资源 想要了解具体可分配的内存量&#xff0c;可以通过【资源管理】功…