【设计模式-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.hqwc.cn/news/229075.html

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

相关文章

什么是Geo Trust OV证书

一、GeoTrust OV证书的介绍 GeoTrust OV证书是由GeoTrust公司提供的SSL证书&#xff0c;它是一种支持OpenSSL的数字证书&#xff0c;具有更高的安全性和可信度。GeoTrust是全球领先的网络安全解决方案提供商&#xff0c;为各类用户提供SSL证书和信任管理服务。GeoTrust OV证书…

在Springboot中操作Redis——五大数据类型

在Java中操作Redis Redis的Java客户端 前面我们讲解了Redis的常用命令&#xff0c;这些命令是我们操作Redis的基础&#xff0c;那么我们在java程序中应该如何操作Redis呢&#xff1f;这就需要使用Redis的Java客户端&#xff0c;就如同我们使用JDBC操作MySQL数据库一样。 Red…

Python 图形用户界面详解(GUI,Tkinter)

文章目录 1 概述1.1 TK&#xff1a;窗口1.2 官方文档 2 组件2.1 Label&#xff1a;标签2.2 Button&#xff1a;按钮2.3 Entry&#xff1a;输入2.4 Text&#xff1a;文本2.5 Radiobutton&#xff1a;单选框2.6 Checkbutton&#xff1a;复选框2.7 Canvas&#xff1a;画布2.10 Men…

【100个Cocos实例】完蛋,你看我在刮刮乐中刮到了什么?

引言 什么&#xff1f;还能刮出这个&#xff1f; 相信大家对刮刮乐都不陌生&#xff0c;昨天听到小伙伴说花了20买了张刮刮乐&#xff0c;结果刮中了20&#xff0c;白忙活一场。 假如我们要在Cocos游戏开发中实现刮刮乐效果&#xff0c;应该怎么做呢&#xff1f; 本文将介绍…

【人工智能】人工智能的技术研究与安全问题的深入讨论

前言 人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;英文缩写为AI。 它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是新一轮科技革命和产业变革的重要驱动力量。 &#x1f4d5;作者简介&#x…

React 之 airbnb - 项目实战

一、开发前言 1. 规范 2. 创建项目 node -v > 18.0.0 npm -v > 8.6.0 create-react-app star-airbnb 3. 项目基本配置 配置jsconfig.json {"compilerOptions": {"target": "es5","module": "esnext","ba…

CCFCSP试题编号:202109-2试题名称:非零段划分

用差分法 #include<iostream> #include<algorithm> #include<cstring> using namespace std;const int N 500000; const int M 10000; int a[N 2 ] { 0 }; int d[M 1] { 0 };int main() {int n;cin >> n;for (int i 1; i < n; i){cin >&g…

Ubuntu:安装Powershell

Powershell的安装与使用&#xff1a; 1&#xff09;安装Powershell&#xff1a;在终端依次运行以下命令即可&#xff1a; $ sudo apt-get update $ sudo apt-get install -y wget apt-transport-https software-properties-common $ wget -q "https://packages.microsof…

【2023CANN训练营第二季】——Ascend C自定义算子工程介绍及实验

一、自定义算子工程介绍与创建 自定义算子工程是一个包含用户编写的host侧和kerne|侧算子实现文件的&#xff0c;用于编译和安装自定义算子run包的工程框架。 CANN软件包中提供了工程创建工具msopgen&#xff0c;开发者可以输入算子原型定义文件生成Ascend C算子开发工程。 需…

JSP forEach 标签遍历map集合

之前我们说了 普通list 单纯按数量循环 bean类型list的遍历方式 那么 我们forEach标签 也能循环map语法非常简单&#xff0c;和循环list基本是一样的 我们直接上jsp代码 <% page import"java.util.Map" %> <% page import"java.util.HashMap" %…

Java 基础学习(二)运算符与分支流程控制

1 运算符 1.1 运算符概述 1.1.1 运算符概述 运算符是一种告诉计算机执行特定的数学或逻辑等操作的符号。Java运算符号包括&#xff1a;数学运算符、关系运算符、逻辑运算符、赋值运算符号、字符串连接运算符。计算机本质上只能处理数字&#xff0c;处理数字的最常见的方式就…

Zabbix 6 详细安装部署教程

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