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

news2024/12/23 19:08:17

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

工厂模式(Factory Pattern)提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可。

简单工厂模式

比如我们有造车的工厂,来生产车,我们先定义一个抽象车产品:

//抽象车产品类
public abstract class AbstractCar { 
    String engine;
    public abstract void run();
}

我们有两个具体的产品,货车和家用小汽车,都继承自抽象车:

//货车
public class Truck extends AbstractCar{
	public Truck() {
        this.engine = "货车引擎";
    }
    @Override
    public void run() {
        System.out.println(this.engine+"--->正在运行");
    }
}
//家用小汽车
public class MiniCar extends AbstractCar{
    public MiniCar() {
        this.engine = "家用小汽车引擎";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "----------》正在运行");
    }
}

那我们的工厂可以如此定义:

public class MySimpleFactory {

   	/**
     * 获取车
     * @param type
     * @return
     */
    public AbstractCar newCar(String type){
        if("truck".equals(type)){
            return new Truck();
        }else if("mini".equals(type)){
            return new MiniCar();
        }

        return null;
    }
}

一般简单工厂生产的产品优先。

测试类如下:

public class SimpleFactoryTest {
    public static void main(String[] args) {
        MySimpleFactory factory = new MySimpleFactory();
        AbstractCar truck = factory.newCar("truck");
        AbstractCar mini = factory.newCar("mini");
        truck.run();
        mini.run();
    }
}

运行如下:

运行效果

缺点

**违反了开闭原则,扩展不易。**如果有大量的产品,会有大量的if else。

工厂方法模式

因为简单工厂模式,会出现大量的if else,并不能满足打开扩展、关闭修改的原则,我们希望,如果有扩展,直接扩展一个类就好,不区改动创造类型的代码,这样工厂方法模式就出现了。我们可以把工厂再进行抽象,把我们的工厂提升一个层次。

抽象类或者接口,就会有多个实现;有多实现 就会有多功能。

抽象工厂如下:

public abstract class AbstarctCarFactory {
    public abstract AbstractCar newCar();
}

我们的货车、小汽车,分别由不同的工厂来创建:

//货车工厂
public class TruckFactory extends AbstarctCarFactory {
    @Override
    public AbstractCar newCar() {
        return new Truck();
    }
}
//小汽车工厂
public class MiniCarFactory extends AbstarctCarFactory {
    @Override
    public AbstractCar newCar() {
        return new MiniCar();
    }
}

测试类如下:

public class FactoryMethodTest {
    public static void main(String[] args) {
        AbstarctCarFactory miniCarFactory = new MiniCarFactory();
        AbstractCar miniCar = miniCarFactory.newCar();
        miniCar.run();

        TruckFactory truckFactory = new TruckFactory();
        AbstractCar truck = truckFactory.newCar();
        truck.run();
    }
}

运行结果如下:

运行结果

这样,如果我们有新的类型,可以直接继承这个抽象工厂即可。

缺点

系统复杂度增加,可创建的品类单一。

抽象工厂模式

我们先来区分两个概念:

  • 产品等级:比如手机可以分为低配版手机、高配版手机;产品等级结构即产品的继承结构,如抽象类为手机,可以有拍照手机、游戏手机等等。
  • 产品族:产品可以分为手机、汽车等,这是产品族。在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。

在车的产品基础上,我们又增加了新的产品,手机。

public abstract class AbstractPhone {
    //手机类型
    String type;
    public abstract void run();
}

public class GamePhone extends AbstractPhone {
    public GamePhone() {
        this.type = "游戏手机";
    }
    @Override
    public void run() {
        System.out.println(this.type + "正在运行了...");
    }
}

public class MyPhotoPhoneFactory implements MyAbstarctFactory{
    @Override
    public AbstractPhone newPhone() {
        return new PhotoPhone();
    }
}

如果我们想生产车和手机,我们可以定义抽象工厂:

public interface  MyAbstarctFactory {
    default AbstractCar newCar(){
        return null;
    }
    default AbstractPhone newPhone(){
        return null;
    }
}

生产手机的工厂分别为:

public class MyGamePhoneFactory implements MyAbstarctFactory{
    @Override
    public AbstractPhone newPhone() {
        return new GamePhone();
    }
}
public class MyPhotoPhoneFactory implements MyAbstarctFactory{
    @Override
    public AbstractPhone newPhone() {
        return new PhotoPhone();
    }
}

生产车的工厂分别为:

public class MyMiniCarFactory implements MyAbstarctFactory{
    @Override
    public AbstractCar newCar() {
        return new MiniCar();
    }
}

public class MyTruckCarFactory implements MyAbstarctFactory{
    @Override
    public AbstractCar newCar() {
        return new Truck();
    }
}

测试类如下:

public class MyTest {
    public static void main(String[] args) {
        MyAbstarctFactory factory = new MyGamePhoneFactory();
        AbstractPhone abstractPhone = factory.newPhone();
        abstractPhone.run();

        factory = new MyMiniCarFactory();
        AbstractCar abstractCar = factory.newCar();
        abstractCar.run();
    }
}

运行如下:

运行结果

可以看到,我们在扩展时,都是新增类,而不是修改原有的方法。

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

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

相关文章

b站so层sign算法

前言 大家好呀,欢迎来到我的博客!!! 本期我将带来b站so层sign算法实现 设备: pixel4 android10 下载地址: aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzI4MTI5MS9oaXN0b3J5X3Y2MTgwNTAw 版本: 6.18.0 工具: charles(抓包) socksdroid(流量转发) jadx(反编译dex) ida(反编…

中微CMS8S3680/69xx系列单片机

最近在使用中微CMS8S3680/69xx系列8位单片机来进行电源控制软件开发。 总体觉得这款单片机简单易用,特别是它的数字功能可以映射到任意脚,甚至包括程序的烧录脚,对于PCB布局特别灵活。另外它的存储器资源也是很丰富的,16K字节ROM…

实战 | SQL注入

一、资产搜集 我们都知道sql注入的传参有些是明文的,有些是经过编码或者加密的,所以我们搜索的时候不要仅限于inurl:.php?id1,可以额外的尝试搜搜1的base64编码值MQ,即可以搜索inurl:.php?idMQ,或者搜索1的md5加密值…

C代码的单元测试

C代码中集成gtest单元测试_gtest测试c语言_山河故人~的博客-CSDN博客 Linux安装gtest_gtest安装_山河故人~的博客-CSDN博客 一:安装gtest: 1. 安装gtest 采用源码安装的方式,需确保cmake已经安装。 git clone https://github.com/google/googletest …

网络安全(黑客)—小白自学路线

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高; 二、则是发展相对成熟…

商业模式画布的9大模块全解读,产品经理不可不知!

“商场如战场”,在当今瞬息万变的商业环境中,创造出独特且创新的商业模式是每个企业家、策略家和决策者的首要任务。为了在激烈的市场竞争中取得优势,我们需要一个强大且直观的工具来帮助我们规划和塑造公司的商业模式,这个经常被…

从零开始实现神经网络(一)_NN神经网络

参考文章:神经网络介绍 一、神经元 这一神经网络的基本单元,神经元接受输入,对它们进行一些数学运算,并产生一个输出。 这里有三步。 首先,将每个输入(X1)乘以一个权重: 接下来&…

如何备份和恢复微信聊天记录?微信聊天记录1分钟轻松备份和恢复。

微信是一个非常流行的应用程序,不仅在中国,而且在全世界。这个应用程序允许来自其他国家的用户与他们的中国朋友进行群聊、语音消息、视频通话、发送贴纸或 GIF 以及照片。它可以为学生和商人/女性发送重要文件,以及位置共享以防游客在访问中…

内网穿透实现在外远程访问NAS威联通(QNAP)

文章目录 前言1. 威联通安装cpolar内网穿透2. 内网穿透2.1 创建隧道2.2 测试公网远程访问 3. 配置固定二级子域名3.1 保留二级子域名3.2 配置二级子域名 4. 使用固定二级子域名远程访问 前言 购入威联通NAS后,很多用户对于如何在外在公网环境下的远程访问威联通NAS…

系列四十、请谈一下Spring中事务的传播行为

一、概述 事务的传播行为指的是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。事务的传播行为至少发生在两个事务方法的嵌套调用中才会出现。 二、传播行为分类

专门解决数学问题的大模型

01 项目介绍 LLEMMA:一个专门解决数学问题的开源大语言模型,能力超过所有已知的开源模型 LLEMMA由多个大学和Eleuther AI公司共同研发,模型能够理解和生成数学表达式、解决数学问题,并与其他计算工具(如Python解释器…

Jenkins Gerrit Trigger插件配置

安装Jenkins 以Jenkins 2.361.1版本为例 docker pull jenkins/jenkins:2.361.1运行容器,将主机的8080端口映射到容器的8080端口,同时将主机的50000端口映射到容器的50000端口(用于构建代理) docker run -d -p 8080:8080 -p 500…

操作系统(Linux)外壳程序shell 、用户、权限

文章目录 操作系统和shell外壳Linux用户普通用户的创建和删除用户的切换 Linux 权限Linux 权限分类文件访问权限修改文件的权限权限掩码粘滞位 大家好,我是纪宁。 这篇文章将介绍 Linux的shell外壳程序,Linux用户切换机Linux权限的内容。 操作系统和shel…

基于SpringBoot的养老院信息管理系统

基于SpringBoot的养老院信息管理系统,java项目,springboot项目,idea都能打开运行。 推荐环境配置:idea jdk1.8 maven mysql5.5/mysql5.7 主要技术: SpringBoot,MySql,ajax,MyBatis 本系统的主要…

Vue 路由指南:畅游单页应用的地图(Vue Router 和 <router-view>)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

STM32F407的系统定时器

文章目录 系统定时器SysTick滴答定时器寄存器STK_CTRL 控制寄存器STK_LOAD 重载寄存器STK_VAL 当前值寄存器STK_CALRB 校准值寄存器 初始化 Systick 定时器SysTick_InitSysTick_CLKSourceConfig delay_us寄存器delay_us库函数delay_xms短时delay_ms长时SysTick_Config 系统定时…

电阻距离------Resistance distance

原来的解释来自维基百科:https://en.wikipedia.org/wiki/Resistance_distance 在图论中,简单连通图G的两个顶点之间的电阻距离等于电网上两个等效点之间的电阻,电网被构造为与G相对应,每条边被一欧姆的电阻代替。它是图上的度量。…

Jenkins安装(Jenkins 2.429)及安装失败解决(Jenkins 2.222.4)

敏捷开发与持续集成 敏捷开发 敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。…

geatpy-遗传算法

参考: geatpy 官网 关注的点 在实操过程中,主要遇到以下问题: 不等式约束代码里怎么写?几种书写方式之间有何细节差别要注意入门案例一 包含不等式约束 import geatpy as ea import numpy as np# 构建问题 r = 1 # 目标函数需要用到的额外数据 @ea.Problem.single def …