【设计模式-2.2】创建型——简单工厂和工厂模式

说明:本文介绍设计模式中,创建型设计模式中的工厂模式;

飞机大战

创建型设计模式,关注于对象的创建,本文介绍的简单工厂和工厂模式同样也是。举一个游戏例子,如飞机大战游戏中,屏幕中敌人类型有坦克、飞机,会随机出现在画面的上方;

在这里插入图片描述
我们可以简单的将敌人抽象为一个抽象类,然后分别创建对应的实现类,如下:

(敌人抽象类,注意属性的修饰符,protected,子类中需要用到)

/*** 敌人抽象类*/
public abstract class Enemy {/*** 敌人的坐标*/protected int x;/*** 敌人的坐标*/protected int y;/*** 抽象方法*/public Enemy(int x, int y) {this.x = x;this.y = y;}/*** 绘制方法*/public abstract void show();
}

(具体实现类,坦克)

/*** 坦克*/
public class Tank extends Enemy{public Tank(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("坦克出现了,坐标是:" + x + "," + y);}
}

(具体实现类,飞机)

/*** 飞机*/
public class AirPlane extends Enemy{public AirPlane(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("飞机出现了,坐标是:" + x + "," + y);}
}

(客户端,client)

import java.util.Random;/*** 客户端*/
public class Client {public static void main(String[] args) {// 屏幕宽度是100int screenLength = 100;// 创建坦克Enemy tank = new Tank(new Random().nextInt(screenLength),0);tank.show();// 创建飞机Enemy airPlane = new AirPlane(new Random().nextInt(screenLength),0);airPlane.show();}
}

执行结果:

在这里插入图片描述

分析:以上创建方式,有两点不足之处,对象的创建和使用在一起,耦合性太高;创建对象的代码放到了客户端类里,如果需要创建多个对象的话,客户端的代码势必会越来越臃肿

简单工厂

为了解决上面提到的两个问题,耦合性高,客户端代码臃肿,我们可以使用简单工厂对上面的流程进行改进。如下,创建一个简单工厂类,将创建对象的步骤抽取到这里面:

import java.util.Random;/*** 简单工厂*/
public class SimpleFactory {/*** 屏幕宽度*/private int screenLength;/*** 随机数*/private Random random;/*** 构造函数** @param screenLength*/public SimpleFactory(int screenLength) {this.screenLength = screenLength;this.random = new Random();}/*** 创建敌人* @param type* @return*/public Enemy createEnemy(String type) {int x = random.nextInt(screenLength);Enemy enemy = null;switch (type) {case "Tank":enemy = new Tank(x, 0);break;case "AirPlane":enemy = new AirPlane(x, 0);break;default:throw new RuntimeException("unknown enemy type");}return enemy;}
}

这样,客户端就可以使用这个简单工厂来创建对象了,如下:

/*** 客户端*/
public class Client {public static void main(String[] args) {int screenLength = 100;new SimpleFactory(screenLength).createEnemy("Tank").show();new SimpleFactory(screenLength).createEnemy("AirPlane").show();}
}

执行结果:

在这里插入图片描述
分析:通过简单工厂,对对象的创建进行了封装,使客户端的代码简单、清爽。但是,如果需要增加敌人类型的话,我们就需要去修改这个简单工厂类,新增case分支,这不利于后续的代码扩展

工厂模式

使用工厂模式,可以弥补简单工厂的缺点。我们可以创建一个工厂接口,让后续所有的敌人对象都实现这个接口,并实现其抽象方法,把对象的创建放到具体实现类中,这样后续无论新增多少种敌人类型,都只要实现这个接口即可,不需要对原有系统进行修改。如下:

(工厂接口)

/*** 敌人工厂接口*/
public interface Factory {/*** 创建敌人* * @param screenLength* @return*/Enemy createEnemy(int screenLength);
}

(飞机工厂)

import java.util.Random;/*** 飞机工厂*/
public class AirPlaneFactory implements Factory{@Overridepublic Enemy createEnemy(int screenLength) {return new AirPlane(new Random().nextInt(screenLength), 0);}
}

(坦克工厂)

import java.util.Random;/*** 坦克工厂*/
public class TankFactory implements Factory{@Overridepublic Enemy createEnemy(int screenLength) {return new Tank(new Random().nextInt(screenLength), 0);}
}

现在,如果需要新增一个Boss对象,只需要创建对应的Boss对象,及其工厂实现类即可,如下:

(Boss类)

/*** Boss*/
public class Boss extends Enemy{public Boss(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("Boss出现了,坐标是:" + x + "," + y);}
}

(Boss工厂实现类,用于创建Boss)

import java.util.Random;/*** Boss工厂*/
public class BossFactory implements Factory {@Overridepublic Enemy createEnemy(int screenLength) {// Boss出现在屏幕正中间return new Boss(screenLength / 2, 0);}
}

(客户端代码,客户端只需创建工厂对象,调用其方法即可)

/*** 客户端*/
public class Client {public static void main(String[] args) {// 屏幕宽度int screenLength = 100;// 创建坦克Factory tankFactory = new TankFactory();for (int i = 0; i < 10; i++) {tankFactory.createEnemy(screenLength).show();}// 创建飞机Factory airFactory = new AirPlaneFactory();for (int i = 0; i < 10; i++) {airFactory.createEnemy(screenLength).show();}// 创建BossFactory boosFactory = new BossFactory();boosFactory.createEnemy(screenLength).show();}
}

执行结果:

在这里插入图片描述

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优维低代码实践:搜索功能

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…

每日一练:约瑟夫生者死者小游戏

1. 问题描述 约瑟夫问题&#xff08;Josephus problem&#xff09;是一个经典的数学和计算机科学问题&#xff0c;源于犹太历史学家弗拉维奥约瑟夫斯&#xff08;Flavius Josephus&#xff09;的著作《犹太战记》。问题的描述如下&#xff1a;   在这个问题中&#xff0c;有n…

uniapp微信小程序中阻止事件冒泡

开发场景&#xff1a;列表中展示地块的数据信息&#xff0c;用户可以点击列表进入地块的详情界面&#xff0c;也可以点击列表中的星星按钮进行收藏 遇到的问题&#xff1a;每次点击星星的时候&#xff0c;都会触发父级的点击事件&#xff0c;从而进入到详情界面 原本的代码&am…

android开发:安卓13Wifi和热点查看与设置功能

近日对安卓热点功能做了一些技术验证&#xff0c;目的是想利用手机开热点给设备做初始化&#xff0c;用的是安卓13&#xff0c;简言之&#xff1a; 热点设置功能不可用&#xff0c;不可设置SSID和密码&#xff0c;不可程序控制开启关闭&#xff0c;网上的代码统统都过时了Loca…

【数据结构】树与二叉树(廿五):树搜索给定结点的父亲(算法FindFather)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲a. 算法FindFatherb. 算法解析c. 代码实现 3. 代码整合 5.3.1 树的存储结构 5. 左儿子右兄弟链接结构 【数据结构】树与二叉树&#xff08;十九&…

ESP32-Web-Server 实战编程-通过网页控制设备多个 GPIO

ESP32-Web-Server 实战编程-通过网页控制设备多个 GPIO 概述 上节 ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO 讲述了如何通过网页控制一个 GPIO。本节实现在网页上控制多个 GPIO。 示例解析 前端设计 前端代码建立了四个 GPIO&#xff0c;如下死 GPIO 2 在前端的…

wmvcore.dll丢失怎么办?解决电脑出现wmvcore.dll丢失问题5个方法

wmvcore.dll缺失5个解决方法与wmvcore.dll丢失原因及文件介绍 引言&#xff1a; 在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是wmvcore.dll缺失。wmvcore.dll是Windows Media Video编码解码相关动态链接库文件之一&#xff0c;它对…

VR全景技术助力政务服务大厅数字化,打造全新政务服务体验

引言&#xff1a; 随着科技的飞速发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术逐渐走进人们的视野。VR全景技术作为VR领域的一项重要应用&#xff0c;以其沉浸式、交互式的特点&#xff0c;正逐渐渗透到各行各业。政务服务大厅作为相关部门与民众之间的桥梁&#…

Elasticsearch(一)

一&#xff1a;简介 The Elastic Stack, 包括 Elasticsearch、 Kibana&#xff08;展示数据的项目&#xff09;、 Beats 和 Logstash&#xff08;这两个是采集和传输数据的项目&#xff09; 这些项目组合形成的技术栈称为ELK Stack&#xff0c;能够安全可靠地获取任何来源、任…

Vue框架学习笔记——键盘事件

文章目录 前文提要键盘事件&#xff08;并不是所有按键都能绑定键盘事件&#xff09;常用的按键不同的tab和四个按键keyCode绑定键盘事件&#xff08;不推荐&#xff09;Vue.config.keyCode.自定义键名 键码 神奇的猜想div标签和click.enterbutton标签和click.enter 前文提要 …

Cesium 展示——地球以及渲染数据导出(下载)为图片或 pdf

文章目录 需求分析新加需求分析第一种方式第二种方式需求 将 Cesium 球体以及渲染数据导出为 jpg/png/pdf 分析 获取场景 scene 信息,转为image 的 octet-stream 流 进行下载为图片 /*** @todo canvas 导出图片* @param {string} dataurl - 地址* @return {Blob}*/ functio…

额,收到阿里云给的赔偿了!

众所周知&#xff0c;就在刚过去不久的11月12号&#xff0c;阿里云突发了一次大规模故障&#xff0c;影响甚广。 以至于连咱们这里评论区小伙伴学校的洗衣机都崩了&#xff08;手动doge&#xff09;。 这么关键的双11节点&#xff0c;这么多热门业务和产品&#xff0c;这么大规…

平凯星辰携手教育部教育管理信息中心,助力普惠教育数字化

近日&#xff0c;企业级开源分布式数据库厂商平凯星辰与教育部教育管理信息中心达成合作&#xff0c;TiDB 分布式数据库为全国中小学管理服务平台提供全栈服务。双方将携手深入探索领先的数据库技术在教育行业的新场景与新应用&#xff0c;既夯实教育数字化底座&#xff0c;助力…

DS八大排序之直接插入排序和希尔排序

前言 我们前面几期介绍了线性和非线性的基本数据结构。例如顺序表、链表、栈和队列、二叉树等~&#xff01;本期和接下来的几期我们来详解介绍各个排序的概念、实现以及性能分析&#xff01; 本期内容 排序的概念以及其运用 常见的排序算法 直接插入排序 希尔排序 一、排序的…

Zabbix 6 详细安装部署教程

目录 一、安装 MySQL 数据库 二、安装 zabbix 监控平台 三、编辑配置文件 四、启动服务 五、zabbix-web 安装 zabbix web 出图展示乱码问题解决方案 zabbix 的安装部署非常简单&#xff0c;官方提供了四种安装途径&#xff0c;分别是二进制 rpm 包安装方式、源码安装方…

jetson nano 串口通信

目录 1.UART通信介绍 2.电脑端准备工作 2.1 安装串口调试助手 2.2 硬件接线 3.Jetson Nano端准备工作 3.1安装库文件 3.2修改主板上电启动串口权限 4.示例程序-发送及接收 4.1 开启串口调试助手 4.2 导入示例程序 4.3 执行程序 4.4 查看效果 4.4.1 串口调试端 4.4…

西南科技大学信号与系统A实验三(线性连续时间系统的分析)

一、实验目的 1.掌握用 matlab 分析系统时间响应的方法 2.掌握用 matlab 分析系统频率响应的方法 3.掌握系统零、极点分布与系统稳定性关系 二、实验原理 1. 系统函数 H(s) 系统函数:系统零状态响应的拉氏变换与激励的拉氏变换之比. H(s)=R(s)/E(s) 在 matlab 中可采用…

ddns-go部署在linux虚拟机

ddns-go部署ubuntu1804 1.二进制部署 1.虚拟机部署 1.下载linux的x86二进制包 wget https://github.com/jeessy2/ddns-go/releases/download/v5.6.3/ddns-go_5.6.3_linux_x86_64.tar.gz2.解压 tar -xzf ddns-go_5.6.3_linux_x86_64.tar.gz3.拷贝执行文件到PATH下&#xff0c…

【前端】浅谈async/await异步传染性

文章目录 概述观点无法解决可以解决 来源 概述 "异步传染性"问题通常是指&#xff0c;当一个函数使用了async和await&#xff0c;其调用者也需要使用async和await处理异步操作&#xff0c;导致整个调用链都变成异步的。这种情况可能导致代码变得更复杂&#xff0c;不…

全网日志智能聚合及问题根因分析

1 日志关联分析的挑战 随着各行各业数字化转型的不断深入&#xff0c;网络承载了人们日常生活所需的政务、金融、娱乐等多方面的业务系统&#xff0c;已经成为影响社会稳定运行、关系国计民生的重要基础设施资源。哪怕网络发生及其微小的故障&#xff0c;也可能带来难以估量的…