学习设计模式之享元模式,但是宝可梦

前言

作者在准备秋招中,学习设计模式,做点小笔记,用宝可梦为场景举例,有错误欢迎指出。

享元模式

1 介绍

享元模式很好理解,它主要是为了减少创建对象的数量,属于结构型设计模式

  • 目的:减少创建对象的次数
  • 方法:复用对象
  • 何时使用:系统大量需要对象,该创建对象的消耗很大

享元模式有3个角色:

  • 抽象享元类(Flyweight):声明享元类的公共方法
  • 具体享元对象(Concrete Flyweight):抽象享元类的具体实现
  • 享元工厂类(Flyweight Factory):创建、管理享元对象。

还是老样子,一上来一堆概念和角色名次,如果不熟悉线程池的读者朋友,或许还是云里雾里。

那么,进入宝可梦世界。

2 情景模拟

在这里插入图片描述

玩过宝可梦的读者都知道,一场战斗开始之前,双方都要携带一定数量的宝可梦,当一方所有宝可梦都战斗不能时,就被判负。

每个回合也可以选择继续出招或者收回宝可梦,如果选择收回,那下次放出来的时候,还是会延续收回之前的状态,因为收回后再拿出来很明显是对同一个宝可梦进行的,皮卡丘收回去之后,这个精灵球里下次出来的还是皮卡丘,而且是收回来的皮卡丘,不是一个满血满状态的。

那么享元模式工厂维护的“享元池”,就有对象第一次创建的时机,可以是第一次使用的时候。

那么一场战斗携带的精灵就是复用的,这也可以引出享元模式的角色:

  • 抽象享元类:宝可梦,定义了公共方法,如登场,掉血
  • 具体享元类:具体的宝可梦
  • 享元工厂类:一场战斗的精灵包,维护全体精灵这个享元池

3 代码

抽象类

/*** 宝可梦抽象类* 对应抽象享元类* Flyweight*/
public interface Pokemon {/*** 宝可梦出场*/void go();/*** 宝可梦在战斗中损失HP* @param damage HP*/void loseHP(Integer damage);
}

具体类

/*** 宝可梦具体实现类* 对应具体享元类* ConcreteFlyweight*/
public class ConcretePokemon implements Pokemon{String name;Integer hp = 100;public ConcretePokemon(String name) {this.name = name;}@Overridepublic void go() {System.out.println("去吧!" + this.name + "! (HP:" + this.hp + ")");}@Overridepublic void loseHP(Integer damage) {this.hp -= damage;}
}

享元工厂

/*** 模拟一场战斗的精灵背包* 对应享元工厂类* FlyweightFactory*/
public class FlyweightFactory {// 用一个哈希表判断对象是否存在private HashMap<String, Pokemon> pokemonPool = new HashMap<>();/*** 获取宝可梦,如果没有出场过,就创建对象* 出场过的就返回之前创建的对象* @param name* @return*/public Pokemon getPokemon(String name){// 用名字获取对象 存在就取出 不存在就创建后存入哈希表if(!pokemonPool.containsKey(name)){pokemonPool.put(name, new ConcretePokemon(name));}Pokemon pokemon = pokemonPool.get(name);pokemon.go();return pokemon;}
}

测试类

模拟一场宝可梦战斗,两位训练家小智satoshi和小茂shigeru分别维护各自的享元池,第一次派出精灵时,创建对象。第一回合战斗中,皮卡丘掉血50。第二回合,小智任然派出皮卡丘,可以看到,皮卡丘还是只有50血,因为是同一个对象

public class FlyWeightDemo {public static void main(String[] args) {// 用工厂模拟2位对战训练家FlyweightFactory satoshi = new FlyweightFactory();FlyweightFactory shigeru = new FlyweightFactory();// 出场Pokemon pikachu = satoshi.getPokemon("皮卡丘");Pokemon charizard = shigeru.getPokemon("喷火龙");// 战斗// 皮卡丘掉了半血pikachu.loseHP(50);// 喷火龙gg...System.out.println("喷火龙倒下了...\n");// 第二轮satoshi.getPokemon("皮卡丘");shigeru.getPokemon("电击魔兽");}
}
去吧!皮卡丘! (HP:100)
去吧!喷火龙! (HP:100)
喷火龙倒下了...去吧!皮卡丘! (HP:50)
去吧!电击魔兽! (HP:100)

4 应用

  • 字符串常量池:创建后的字符串会保存在常量池中以供复用
String a = "h";
String b = "h";
System.out.println(a == b);  // true
  • Integer缓存:Integer提供了[-127,128]范围的缓存
Integer a = 123;
Integer b = 123;
System.out.println(a == b);
  • 数据库连接池
  • 线程池

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

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

相关文章

DDR与PCIe:高性能SoC的双引擎

SoC芯片无处不在&#xff0c;小到家电控制的MCU&#xff0c;大到手机芯片&#xff0c;我们都会接触到。如今大部分芯片设计公司都在开发SoC芯片&#xff0c;一颗SoC芯片可以集成越来越多的功能&#xff0c;俨然它已成为IC设计业界的焦点。 高性能、高速、高带宽的互联和存储的…

Redis 执行 RDB 快照期间,主进程可以正常处理命令吗?

执行了 save 命令&#xff0c;会在主进程生成 RDB 文件&#xff0c;由于和执行操作命令在同一个线程&#xff0c;所以如果写入 RDB 文件的时间太长&#xff0c;会阻塞主进程。 执行 bgsave 过程中&#xff0c;由于是交给子进程来构建 RDB 文件&#xff0c;主进程还是可以继续工…

Docker安装及Docker构建简易版Hadoop生态

一、首先在VM创建一个新的虚拟机将Docker安装好 更新系统&#xff1a;首先打开终端&#xff0c;更新系统包列表。 sudo apt-get update sudo apt-get upgrade下图是更新系统包截图 安装Docker&#xff1a;使用以下命令在Linux上安装Docker。 sudo apt-get install -y docker.i…

【ulimit 命令】LINUX单进程能够打开的最大文件句柄数

Linux系统如何查看修改最大打开文件数&#xff0c;这个问题对于很多刚刚学习linux的小伙伴来说觉得有点奇怪。Linux系统和windows不同之处在于更强的多任务多线程&#xff0c;由于文件系统结构的不同linux针对不同进程不同用户都可以设置最打打开文件数。 查看当前系统最大的文…

Python自动化小技巧21——实现PDF转word功能(程序制作)

案例背景 为什么这个年代PDF转word&#xff0c;某wps居然还要收费.....很多软件都可以实现这个功能&#xff0c;但是效果都有好有坏&#xff0c;而且有的还付费&#xff0c;很麻烦。 那就用python实现这个功能吧&#xff0c;然后把代码打包为.exe的程序&#xff0c;这样随便在…

matlab使用教程(25)—常微分方程(ODE)选项

1.ODE 选项摘要 解算 ODE 经常要求微调参数、调整误差容限或向求解器传递附加信息。本主题说明如何指定选项以及每个选项与哪些微分方程求解器兼容。 1.1 选项语法 使用 odeset 函数创建 options 结构体&#xff0c;然后将其作为第四个输入参数传递给求解器。例如&#xff0…

腾讯云服务器地域和可用区详细介绍_选择攻略

腾讯云服务器地域有什么区别&#xff1f;怎么选择比较好&#xff1f;地域选择就近原则&#xff0c;距离地域越近网络延迟越低&#xff0c;速度越快。关于地域的选择还有很多因素&#xff0c;地域节点选择还要考虑到网络延迟速度方面、内网连接、是否需要备案、不同地域价格因素…

Elasticsearch算分优化方案之rescore_query

简介 今天来说一说Elasticsearch 的重新评分&#xff0c;即在检索出来一次结果的基础上在进行检索提升数据排序效果&#xff0c;但是仅对查询或者post_filter阶段返回的前多少条进行二次查询。在每个分片上进行二次检索的文档数量时可以通过window_size 控制的&#xff0c;该参…

论文及代码详解——HRNet

文章目录 论文详解 &#xff08;High-Resolution Networks&#xff09;Parallel Multi-Resolution ConvolutionsRepeated Multi-Resolution FusionsRepresentation Head 代码详解 论文&#xff1a;《Deep High-Resolution Representation Learning for Visual Recognition》 代…

选择排序:用C语言打造高效的排序算法

本篇博客会讲解如何使用C语言实现选择排序。 下面我来画图讲解选择排序的思路。 假设有一个数组&#xff0c;其初始状态如下&#xff0c;我们想把这个数组排成升序。 首先我们标明范围&#xff0c;即[begin, end]&#xff0c;一开始begin(b)和end(e)分别表示数组的第一个位置…

UE4/5Niagara粒子特效之Niagara_Particles官方案例:3.3->4.3

目录 3.3 Visibility Tag 左边的发射器&#xff1a; 发射器更新 粒子生成 粒子更新 右边的发射器 和左边发射器不同的地方 3.4 Texture Sampling 发射器更新 粒子生成 粒子更新 4.1Play Audio Per Particle 系统 第三个发射器 发射器更新 粒子生成 粒子更新 第二个…

第一个VUE程序?

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title></head> <body><div id"app">{{message}} </div><!-- 1.导入Vue.js --> <script s…

【C进阶】指针(一)

大家好&#xff0c;我是深鱼~ 【前言】&#xff1a; 指针的主题&#xff0c;在初阶指针章节已经接触过了&#xff0c;我们知道了指针的概念&#xff1a; 1.指针就是个变量&#xff0c;用来存放地址&#xff0c;地址的唯一标识一块内存空间&#xff08;指针变量&#xff09;&a…

无涯教程-机器学习 - 数据加载

假设如果要启动ML项目&#xff0c;那么您需要做的第一件事也是最重要的事情是什么?这是无涯教程启动任何ML项目都需要加载的数据。关于数据&#xff0c;对于ML项目&#xff0c;最常见的数据格式是CSV(逗号分隔值)。 基本上&#xff0c;CSV是一种简单的文件格式&#xff0c;用…

RocketMQ同步复制和异步复制

如果一个Broker组有Master和Slave&#xff0c;消息需要从Master复制到Slave上&#xff0c;有同步和异步两种复制方式。 1)同步复制 同步复制方式是等Master和Slave均写成功后才反馈给客户端写成功状态&#xff1b; 在同步复制方式下&#xff0c;如果Master出故障&#xff0c…

【数据结构】如何用栈实现队列?图文解析(LeetCode)

LeetCode链接&#xff1a;232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 注&#xff1a;本文默认读者已掌握栈与队列的基本操作 可以看这篇文章熟悉知识点&#xff1a;【数据结构】栈与队列_字节连结的博客-CSDN博客 目录 做题思路 代码实现 1. MyQueue 2. …

【Python】从入门到上头—Python基础(2)

文章目录 一.基础语法1.编码2.标识符3.保留字4.注释5.行与缩进6.多行语句7.数字(Number)类型8.字符串(String)9.空行10.等待用户输入11.同一行显示多条语句12.多个语句构成代码组13.print 输出14.import 与 from...import 二.基本数据类型1.变量和赋值2.多个变量赋值3.标准数据…

2023.8 -java - 继承

继承就是子类继承父类的特征和行为&#xff0c;使得子类对象&#xff08;实例&#xff09;具有父类的实例域和方法&#xff0c;或子类从父类继承方法&#xff0c;使得子类具有父类相同的行为。 继承的特性 子类拥有父类非 private 的属性、方法。 子类可以拥有自己的属性和方法…

数据库连接池druid 的jar包官网下载-最新版下载

进入官网Central Repository: com/alibaba/druid 往下滑 找到最新版点击进入 找到该jar包 点击即可下载

【HCIP】04.VRRP与BFD

VRRP VRRP基本概念 VRRP路由器 运行VRRP协议的路由器&#xff0c;VRRP是配置在路由器的接口上的&#xff0c;而且也是基于接口来工作的。 VRID 一个VRRP组由多台协同工作的路由器&#xff08;的接口&#xff09;组成&#xff0c;使用相同的VRID&#xff08;Virtual Router…