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

news2024/12/23 4:35:25

前言

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

享元模式

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;
    }

    @Override
    public void go() {
        System.out.println("去吧!" + this.name + "! (HP:" + this.hp + ")");
    }

    @Override
    public 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.coloradmin.cn/o/914285.html

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

相关文章

【第三阶段】kotlin语言的内置函数run

1.run函数返回类型是根据匿名函数最后一行的类型变化而变化 run 函数里面持有的是this fun main() {val info"kotlin is ok"var r info.run {true}println(r) }执行结果 2.run搭配具名函数 package Stage3fun main() {val info"kotlin is ok"var r info…

IAR编译报错 ErrorLi005]: no definition for

IAR编译报错 ErrorLi005]: no definition for… 具体报错如下图所示&#xff1a; 错误原因&#xff1a;出现此问题是由于没有写 VehicleDriveStatusCheck 此功能函数&#xff0c;而程序中其他地方调用此函数而导致的错误 解决措施&#xff1a;编写 VehicleDriveStatusCheck …

docker的安装以及基本操作

一.认识docker Docker是一种用于构建、打包和运行应用程序的开源平台。它基于操作系统级虚拟化技术&#xff0c;可以将应用程序和其依赖的库、环境等资源打包到一个可移植的容器中&#xff0c;形成一个轻量级、独立的可执行单元。 开发者在本地编译测试通过的容器可以批量地在…

Win 7 修改开机密码,使用F8修复提前终止导致蓝屏

前言 一台win7一体机密码突然不对&#xff0c;也不知道怎么回事就登录不了 使用PE中的NTPWEdit查看修改密码&#xff0c;没有用户列表 步骤 正常启动或者按F8&#xff0c;选择修复 正常电脑如下显示 这种可以直接使用PE改密码&#xff0c;就不放图了 问题电脑如下显示…

kafka--技术文档--基本docker中安装<单机>-linux

安装zookeeper 阿丹小科普&#xff1a; Kafka在0.11.0.0版本之后不再依赖Zookeeper&#xff0c;而是使用基于Raft协议的Kafka自身的仲裁机制来替代Zookeeper。具体来说&#xff0c;Kafka 2.8.0版本是第一个不需要Zookeeper就可以运行Kafka的版本&#xff0c;这被称为Kafka Raf…

C#详解-Contains、StartsWith、EndsWith、Indexof、lastdexof

目录 简介: 过程: 举例1.1 举例1.2 ​ 总结: 简介: 在C#中Contains、StarsWith和EndWith、IndexOf都是字符串函数。 1.Contains函数用于判断一个字符串是否包含指定的子字符串&#xff0c;返回一个布尔值&#xff08;True或False&#xff09;。 2.StartsWith函数用于判断一…

Vue Element upload组件和Iview upload 组件上传文件

今天要分享的是使用这俩个UI组件库的upload组件分别实现调用组件本身的上传方法实现和后台交互。接下来就是开车的时间&#xff0c;请坐稳扶好~ 一、element upload组件传送门 1、html文件 <el-upload ref"uploadRef" :action"uploadUrl" :data"…

第五讲:常见的BeanPostProcessor

常见的BeanPostProcessor 一、入门Demo二、添加BeanPostProcessor1. AutowiredAnnotationBeanPostProcessor2. CommonAnnotationBeanPostProcessor3. ConfigurationPropertiesBindingPostProcessor 前文我们简单讲了Bean的生命周期&#xff0c;以及生命周期的前后&#xff0c;本…

科大讯飞AI大模型,太猛了!

最近几个月&#xff0c;以ChatGPT为代表的AIGC迅速崛起&#xff0c;国内头部科技企业之间也掀起了百模大战&#xff0c;在众多的大模型当中我比较看好的一家就是&#xff1a;科大讯飞。 我很早就通过科大讯飞老朋友&#xff0c;拿到了体验账号&#xff0c;简单体验了一下&…

C++新经典06-- 语言特性

1.继承性、多态性、封装性。 2.C本身是属于编译型语言。 什么叫编译型语言呢&#xff1f;程序在执行之前需要一个专门的编译过程&#xff0c;把程序编译成二进制文件&#xff08;可执行文件&#xff09;&#xff0c;执行的时候&#xff0c;不需要重新翻译&#xff0c;直接使用…

shell脚本中linux命令的特殊用法记录

shell脚本中linux命令的特殊用法记录 1、linux命令特殊参数选项1.1、sed -e1.2、echo -e 2、 shell 扩展2.1、[[ ]]支持用~进行正则匹配 3、特殊命令用法3.1、{} 变量替换 1、linux命令特殊参数选项 1.1、sed -e sed -e以严格模式执行脚本&#xff0c;在sed -e 后面的所有命令…

反转链表II

江湖一笑浪滔滔&#xff0c;红尘尽忘了 题目 示例 思路 链表这部分的题&#xff0c;不少都离不开单链表的反转&#xff0c;参考&#xff1a;反转一个单链表 这道题加上哨兵位的话会简单很多&#xff0c;如果不加的话&#xff0c;还需要分情况一下&#xff0c;像是从头节点开始…

【Apollo学习笔记】——规划模块TASK之PATH_BORROW_DECIDER

文章目录 前言PATH_BORROW_DECIDER功能简介PATH_BORROW_DECIDER相关配置PATH_BORROW_DECIDER总体流程PATH_BORROW_DECIDER相关子函数IsNecessaryToBorrowLaneIsBlockingObstacleFarFromIntersectionIsNonmovableObstacleCheckLaneBorrow 参考 前言 在Apollo星火计划学习笔记—…

MySql014——分组的GROUP BY子句和排序ORDER BYSELECT子句顺序

前提&#xff1a;使用《MySql006——检索数据&#xff1a;基础select语句》中创建的products表 一、GROUP BY子句基础用法 SELECT vend_id, COUNT(*) AS num_prods FROMstudy.products GROUP BY vend_id;上面的SELECT语句指定了两个列&#xff0c;vend_id包含产品供应商的ID&…

Protobuf 语法详解

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

mybatisplus批量写入

1.新建MybatisPlusConfig /*** MybatisPlusConfig.*/ Configuration MapperScan("com.test.mapper") public class MybatisPlusConfig {/*** 自定义批量插入 SQL 注入器.*/Beanpublic InsertBatchSqlInjector insertBatchSqlInjector() {return new InsertBatchSqlI…

微服务(多级缓存)

多级缓存 1.什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;如图&#xff1a; 存在下面的问题&#xff1a; 请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈Redis缓存失效时&…

【Kubernetes】Kubernetes的监控工具Promethues

Prometheus 一、Prometheus 概念1. Prometheus 概述2. Prometheus 的监控数据3. Prometheus 的特点4. Prometheus 和 zabbix 区别5. Prometheus 的生态组件5.1 Prometheus server5.2 Client Library5.3 Exporters5.4 Service Discovery5.5 Alertmanager5.6 Pushgateway5.7 Graf…

【PHP面试题81】php-fpm是什么?它和PHP有什么关系

文章目录 &#x1f680;一、前言&#xff0c;php-fpm是什么&#x1f680;二、php-fpm与PHP之间的关系&#x1f680;三、php-fpm解决的问题&#x1f50e;3.1 进程管理&#x1f50e;3.2 进程池管理&#x1f50e;3.3 性能优化&#x1f50e;3.4 并发处理 &#x1f680;四、php-fpm常…

每日一题——排序链表(递归 + 迭代)

排序链表&#xff08;递归 迭代&#xff09; 题目链接 注&#xff1a;本体的解法建立在归并排序的基础之上&#xff0c;如果对这一排序还不太了解&#xff0c;建议看看&#xff1a; &#x1f449;归并排序 &#x1f449;八大排序算法详解 &#x1f449;合并两个有序链表 既…