当前位置: 首页 > news >正文

Android 架构模式之 MVP

目录

  • 架构设计的目的
  • 对 MVP 的理解
  • 代码
    • Model
    • View
    • Presenter
  • Android 中 MVP 的问题
  • 试吃个小李子
    • Model
    • View
    • Presenter

大家好!

作为 Android 程序猿,你有研究过 MVP 架构吗?在开始接触 Android 那一刻起,我们就开始接触 MVC 架构,可谓是用的不亦乐乎。可为什么又出现了 MVP 呢?都说它比 MVC 好,到底又好在哪里呢?

架构设计的目的

通过设计使程序模块化,模块内 高内聚、模块间 低耦合,提高开发效率,便于复用及后续维护。

对 MVP 的理解

MVP 架构图,箭头代表事件流向

上图是 MVP 的架构图,我们都知道,MVP架构中 M 代表 Model(模型)、V 代表 View(视图)、P 代表 Presenter(主持人/控制器)。它们的职责分别是:

  1. View 负责接收用户的输入事件,然后将事件传递给 Presenter;
  2. Presenter 收到事件后,会进行业务分发,通知 Model 获取数据;
  3. Model 区分数据来源,进而通过不同渠道获取数据,拿到数据后返回给 Presenter;
  4. Presenter 进行后续处理,或者通知 View 更新 UI。

相比 MVC 架构,MVP 架构看上去就清晰了很多:事件由 View 流向 Presenter 流向 Model,然后再由 Model 流回 Presenter 流回 View。在 MVP 架构中,Activity 就全心的处理着和 View 相关的事情,Model 负责向下分发数据请求,替 Presenter 分担了很大一部分负担,这里特意新增了一个 CacheRepository 来体现提取 Model 层的用意,这样就可以在 Model 层进行不同渠道的分发,既体现了单一职责原则,又很好的提高了代码的可读性。所以看上去是多了一层 Model 层,可实际上作用还是很大的。另外,由于 MVP 是基于接口编程,所以会多了很多接口文件,来定义业务约束,虽然看上去需要新增很多文件/函数,或者理解为额外工作量,但其实这也很好地锻炼架构思维和抽象能力,因为你可以完全放下业务实现来搭建整体框架。

代码

Model

IModel.java

public interface IModel {}

BaseModel.java

public abstract class BaseModel implements IModel {}

View

public interface IView {void showErr(String errMsg);
}

BaseActivity.java

public abstract class BaseActivity<P extends IPresenter> extends AppCompatActivityimplements IView {protected P mPresenter;public BaseActivity() {this.mPresenter = createPresenter();mPresenter.attachView(this);}public abstract P createPresenter();@Overrideprotected void onDestroy() {super.onDestroy();// Activity 销毁时,需要调用 detachView,防止内存泄漏if (mPresenter != null) {mPresenter.detachView();mPresenter.onDestroy();mPresenter = null;}}@Overridepublic void showErr(String errMsg) {Toast.makeText(this, errMsg, Toast.LENGTH_SHORT);}
}

Presenter

IPresenter.java

public interface IPresenter<V extends IView> {void attachView(V view);void detachView();void onDestroy();
}

BasePresenter.java

public abstract class BasePresenter<V extends IView, M extends IModel> implements IPresenter<V> {protected WeakReference<V> mView;protected M mModel;public BasePresenter() {this.mModel = createModel();}protected abstract M createModel();@Overridepublic void attachView(V view) {mView = new WeakReference<>(view);}@Overridepublic void detachView() {if (mView.get() != null) {mView.clear();}}@Overridepublic void onDestroy() {if (mModel != null) {mModel = null;}}
}

上述代码中可以看到,Presenter 中持有 View 引用,想象一种情况,Activity 发起一个网络请求/耗时操作,Presenter 收到需求后就分发去处理需求并等待结果了,但是还没等处理结束,Activity 就执行关闭操作了,此时 Presenter 还持有着 Activity 的强引用,导致 Activity 无法被及时回收掉,这便导致了大名鼎鼎的内存泄漏了;上述代码中通过 WeakReference 持有 View 引用,这样可以有效解决内存泄漏问题,并且在涉及到 Model/View/Presenter 的引用调用的地方,都进行了非空判断,需要规避空指针的风险出现。

Android 中 MVP 的问题

不幸的是,MVP 中 Presenter 的职责就是 MVC 中 Controller 负责的内容,只不过在 Android 中 Controller 在全职作 控制器 的同时,还需要兼职一部分 View 的职责,而 Presenter 就只是全职作 控制器。所以 Presenter 同样存在 Controller 存在的问题,随着业务的增多,Presenter 会变得越拉越 臃肿/复杂,以及 很糟糕的代码可读性

另外,由于 MVP 模式依赖于接口,所以在新增一个业务需求时,会 爆炸式增长文件和函数,这个也很让人头疼。

其次,由于 View 会只有 Presenter 引用,Presenter 持有 View 和 Model 的引用,如果处理不当,也会存在 空指针 的风险。

最后,Presenter 会持有 View 的引用,这样就埋下了 内存泄漏 的种子,如果处理不好,问题还是蛮大的。所以就有了后来的MVVM。

试吃个小李子

点击按钮,请求 wanandroid 网站的 banner 接口数据,请求成功后更新到UI上显示接口数据

代码结构

MVP 架构的 Demo 是从 MVC 架构那套代码变更过来的,添加了很多文件,主要部分 涉及上图中展开的这几个文件,仔细看上图蓝框中的内容会发现,新增一个业务 Activity,共需要新增 6 个文件,其中 3 个是接口约束类、3 个是具体实现类,这也体现了上面说的文件/函数暴增的问题。

Model

请求接口
缓存数据

IMainModel.java

public interface IMainModel extends IModel {/*** 请求 banner 数据** @param callback*/void getNetworkBanner(ResponseCallback<List<Banner>> callback);/*** 读取 banner 本地数据** @return*/List<Banner> getLocalBanner();/*** 持久化存储 banner 数据** @param banners*/void saveBanner(List<Banner> banners);/*** 清空本地数据*/void clearLocalData();
}

MainModel.java

public class MainModel extends BaseModel implements IMainModel {@Overridepublic void getNetworkBanner(ResponseCallback<List<Banner>> callback) {// 收到需求,请求接口数据NetworkRepository.getInstance().requestBanners(callback);}@Overridepublic List<Banner> getLocalBanner() {// 收到需求,读取本地数据return CacheRepository.getInstance().getBanners();}@Overridepublic void saveBanner(List<Banner> banners) {// 收到需求,持久化存储 banner 数据CacheRepository.getInstance().saveBanners(banners);}@Overridepublic void clearLocalData() {// 收到需求,清空本地缓存数据CacheRepository.getInstance().clearLocalData();}
}

View

Button1,点击请求接口数据
Button2,获取本读缓存数据
Button3,清空本地缓存数据
TextView,用于回显数据

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"tools:context=".main.MainActivity"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="getNetworkInfo"android:text="@string/get_network_info" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="getLocalInfo"android:text="@string/get_local_info" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="clearLocalInfo"android:text="@string/clear_local_info" /><TextViewandroid:id="@+id/tv_banner_info"android:layout_width="wrap_content"android:layout_height="wrap_content" /></LinearLayout>

IMainView.java

public interface IMainView extends IView {/*** 更新 banner 数据** @param banners*/void updateBanner(List<Banner> banners, String from);
}

MainActivity.java

public class MainActivity extends BaseActivity<IMainPresenter> implements IMainView {private TextView mBannerInfoTv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mBannerInfoTv = (TextView) findViewById(R.id.tv_banner_info);}@Overridepublic IMainPresenter createPresenter() {return new MainPresenter();}/*** 按钮点击事件** @param view*/public void getNetworkInfo(View view) {// 收到点击事件,交给 presenter 进行业务处理if (mPresenter != null) {mPresenter.getNetworkBanner();}}/*** 按钮点击事件** @param view*/public void getLocalInfo(View view) {// 收到点击事件,交给 presenter 进行业务处理if (mPresenter != null) {mPresenter.getLocalBanner();}}/*** 按钮点击事件** @param view*/public void clearLocalInfo(View view) {// 收到点击事件,交给 presenter 进行业务处理if (mPresenter != null) {mPresenter.clearLocalData();}}@Overridepublic void updateBanner(List<Banner> banners, String from) {// 收到更新 ui 事件,更新 uishowBannerInfo(banners, from);}/*** 更新UI** @param banners*/private void showBannerInfo(List<Banner> banners, String from) {StringBuilder sb = new StringBuilder();if (banners.size() > 0) {sb.append("wanandroid 官网\nhttps://www.wanandroid.com\n\n").append("data from ").append(from).append(":\n");for (Banner item : banners) {Log.e("banner", item.toString());sb.append(item.getTitle()).append('\n');}}mBannerInfoTv.setText(sb.toString());}
}

Presenter

业务处理

IMainPresenter.java

public interface IMainPresenter<V extends IView> extends IPresenter<V> {/*** 获取 banner 网络数据*/void getNetworkBanner();/*** 获取 banner 本地数据*/void getLocalBanner();/*** 存储 banner 数据** @param banners*/void saveBanner(List<Banner> banners);/*** 清空本地数据*/void clearLocalData();
}

MainPresenter.java

public class MainPresenter extends BasePresenter<IMainView, IMainModel>implements IMainPresenter<IMainView> {@Overrideprotected IMainModel createModel() {return new MainModel();}@Overridepublic void getNetworkBanner() {if (mModel == null) {return;}// 收到新需求,分发给 model 处理mModel.getNetworkBanner(new ResponseCallback<List<Banner>>() {@Overridepublic void onSuccess(List<Banner> banners) {// 数据缓存saveBanner(banners);// 通知更新UInotifyUpdateBanner(banners, CommonConstant.FROM_NETWORK);}@Overridepublic void onFail(String msg) {IMainView view = mView.get();if (view != null) {view.showErr(msg);}}});}@Overridepublic void getLocalBanner() {if (mModel == null) {return;}// 收到新需求,分发给 model 处理List<Banner> banners = mModel.getLocalBanner();// 通知更新UInotifyUpdateBanner(banners, CommonConstant.FROM_LOCAL);}@Overridepublic void saveBanner(List<Banner> banners) {// 收到新需求,分发给 model 处理if (mModel != null) {mModel.saveBanner(banners);}}@Overridepublic void clearLocalData() {// 收到新需求,分发给 model 处理if (mModel != null) {mModel.clearLocalData();}}/*** 通知更新UI** @param banners*/private void notifyUpdateBanner(List<Banner> banners, String from) {// 获取到数据,通知更新 uiif (mView != null) {IMainView view = mView.get();if (view != null) {view.updateBanner(banners, from);}}}
}

附上源码链接

致谢:
感谢 wanandroid 提供的开放API

参考:
一个小例子彻底搞懂 MVP

写在最后:
很荣幸成为一名 Android 程序猿,虽然不是一名合格的猿。一路走来磕磕绊绊,借此感谢帮助过我的人,感谢指点、感恩遇见!

相关文章:

Android 架构模式之 MVP

目录 架构设计的目的对 MVP 的理解代码ModelViewPresenter Android 中 MVP 的问题试吃个小李子ModelViewPresenter 大家好&#xff01; 作为 Android 程序猿&#xff0c;你有研究过 MVP 架构吗&#xff1f;在开始接触 Android 那一刻起&#xff0c;我们就开始接触 MVC 架构&am…...

Ciallo~(∠・ω・ )⌒☆第二十二篇 入门request请求库使用

请求库是用于发送HTTP请求的工具。常见的请求库有requests&#xff0c;它是一个功能强大且易于使用的HTTP库。 使用requests库发送GET请求&#xff1a; import requests url "https://httpbin.org/get"# 携带get请求参数 params {"pn": 10,"size&q…...

设计模式-创建型模式-原型模式

1.原型模式定义 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象&#xff1b; 1.1 原型模式优缺点 优点 当创建一个新的对象实例较为复杂时&#xff0c;使用原型模式可以简化对象的创建过程&#xff0c;通过复制一个已有的实例…...

遗传算法与深度学习实战(7)——使用遗传算法解决N皇后问题

遗传算法与深度学习实战&#xff08;7&#xff09;——使用遗传算法解决N皇后问题 0. 前言1. N 皇后问题2. 解的表示3. 遗传算法解决 N 皇后问题小结系列链接 0. 前言 进化算法 (Evolutionary Algorithm, EA) 和遗传算法 (Genetic Algorithms, GA) 已成功解决了许多复杂的设计…...

R语言:如何安装包“linkET”

自己在R语言中安装包“linkET”时报错不存在叫‘linket’这个名字的程辑包 尝试了install.packages("linkET")和BiocManager::install("linkET")两种安装办法都不行 >install.packages("linkET") WARNING: Rtools is required to build R pa…...

JSON, YAML, XML, CSV交互可视化

1、jsoncrack https://jsoncrack.com/editor...

Android UI:PopupWindow:源码分析:设置WindowManager.LayoutParams中的各种参数

文章目录 设置flags是否包含某些flag设置gravity设置type设置softInputMode设置windowAnimations设置width/height设置token 在WindowManager.addView之前设置在WindowManager.addView之后,可通过i熬夜难过update方法设置设置format设置flags是否包含某些flag 1666 …...

MySQL:从入门到放弃

基础查询 MySQL&#xff1a;基础查询 Mybatis&#xff1a;基础巩固-DDL 项目实战 MySQL&#xff1a;按照日期分组查询 查询开始时间与结束时间在指定的日期范围之内&#xff0c;并且结束时间可以为NULL的数据...

C++OpenGL三维显示镜面反射光线漫反射实例

程序示例精选 COpenGL三维显示镜面反射光线漫反射实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《COpenGL三维显示镜面反射光线漫反射实例》编写代码&#xff0c;代码整洁&#xff0c;…...

【前端面试】从npm 升级到 pnpm的总结

pnpm优势 pnpm 和 npm 在性能上存在一些明显的差异,这也是一些开发者选择从 npm 切换到 pnpm 的原因。以下是一些关键的差异和原因: 1. 速度: pnpm 比 npm 快了近 2 倍,它通过优化的依赖管理,显著提高了安装速度 。 2. 磁盘空间效率: pnpm 使用基于内容寻址的文件系…...

同步外网YUM源-3

在企业实际应用场景中,仅仅靠光盘里面的RPM软件包是不能满足需要,我们可以把外网的YUM源中的所有软件包同步至本地,可以完善本地YUM源的软件包数量及完整性。 获取外网YUM源软件常见方法包括Rsync、Wget、Reposync,三种同步方法的区别Rsync方式需要外网YUM源支持RSYNC协议…...

Linux的oracle数据库导入其他用户导出的数据库文件

如果用户使用的是expdp的命令&#xff0c;导入就要使用impdp命令&#xff0c;本文以impdp为例进行介绍 1、查看当前创建的所有dmp导出目录 select * from dba_directories 2、为创建的目录赋权限 比如咱们将数据库导入到test用户&#xff0c; grant read,write on directo…...

FLUX.1 文生图模型微调指南

FLUX.1 是 Black Forest Labs 今年夏天发布的文本转图像模型系列。FLUX.1 模型为开源图像生成模型树立了新标准&#xff1a;它们可以生成逼真的手、清晰的文本&#xff0c;甚至可以生成搞笑表情包这样异常困难的任务。 现在&#xff0c;你可以使用 Ostris 的 Replicate 上的 A…...

JavaWeb基础:HTTP协议与Tomcat服务器

目录 1. HTTP协议简介 示例代码&#xff1a;创建HTTP GET请求 2. Tomcat服务器介绍 Tomcat的基本操作 示例代码&#xff1a;部署简单Servlet 3. 使用Servlet处理请求 示例代码&#xff1a;处理POST请求 在现代网络开发中&#xff0c;理解HTTP协议和如何使用Tomcat作为服…...

python井字棋游戏设计与实现

python实现井字棋游戏 游戏规则&#xff0c;有三个井字棋盘&#xff0c;看谁连成的直线棋盘多谁就获胜 棋盘的展现形式为 棋盘号ABC和位置数字1-9 输入A1 代表在A棋盘1号位数下棋 效果图如下 部分源码如下&#xff1a; 卫星工纵浩 白龙码程序设计&#xff0c;点 代码获取 …...

据说是可以和 Windows 一拼的 5个 Linux 发行版

现如今有数以千计的 Linux 发行版可供您使用&#xff0c;然而人们却无法选择一个完美的操作系统来替代 Windows。 使用 Windows 时&#xff0c;傻瓜都能操作自如&#xff0c;同样的方法却不适用于 Linux。在这里&#xff0c;您必须具备操作和使用操作系统的基本知识。因此人们经…...

PHP 常用函数

1. ksort&#xff08;&#xff09; 如果你有一个数组 array&#xff08;[11] > array(XX), [6] > array(YYY)&#xff09;&#xff0c;你想要返回按照key重新排序&#xff0c;并不改变键和值之间的关联&#xff0c;处理之后的结果为 array&#xff08;[6] > array(YY…...

如何将MySQL迁移到TiDB,完成无缝业务切换?

当 MySQL 数据库的单表数据量达到了亿级&#xff0c;会发生什么&#xff1f; 这个现象表示公司的业务上了一个台阶&#xff0c;随着数据量的增加&#xff0c;公司规模也进一步扩大了&#xff0c;是非常喜人的一个改变 &#xff0c;然而随之而来的其他变化&#xff0c;就没那么…...

【嵌入式烧录刷写文件】-2.10-为一个Intel Hex文件计算校验和Checksum

案例背景(共6页精讲): 有如下一段Intel Hex文件&#xff0c;为其创建Checksum校验和&#xff1a;CRC16&#xff0c;CRC32(CVN)&#xff0c;SHA-256 Hash算法…, 将Checksum Value填充到指定地址。 :2091000058595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767…...

整体思想以及取模

前言&#xff1a;一开始由于失误&#xff0c;误以为分数相加取模不能&#xff0c;但是其实是可以取模的 这个题目如果按照一般方法&#xff0c;到达每个节点再进行概率统计&#xff0c;但是不知道为什么只过了百分之十五的测试集 题目地址 附上没过关的代码 #include<bits…...

RabbitMQ 消息可靠保障

RabbitMQ 消息可靠保障 消息的可靠性保证生产者重连生产者确认解决思路A-确认机制解决思路B-备份交换机 MQ 服务器宕机导致消息丢失消费端消息的可靠性保障 消费端限流给消息生成唯一id 消息的可靠性保证 实际项目中 MQ 的流程一般是&#xff1a;生产端把消息路由到交换机&…...

Redis 作为 PHP 的会话存储

使用 Redis 作为 PHP 的会话存储&#xff0c;可以实现多个服务器之间的会话共享&#xff0c;提高会话管理的效率&#xff0c;特别是在分布式系统中。这种方法将会话数据存储在 Redis 中&#xff0c;而不是使用默认的文件系统&#xff0c;从而使多个服务器可以访问相同的会话数据…...

基于伏图的数字心脏模拟仿真APP应用介绍

一、背景介绍 心脏是保证人体正常运转最重要的动力&#xff0c;人体内的血液循环通过心血管运输到各个部位&#xff0c;因此&#xff0c;心血管系统的稳定是人体健康的关键。心血管内科领域极具专业性&#xff0c;其理论研究与技术发展日新月异&#xff0c;心血管疾病患者往往…...

智云-一个抓取web流量的轻量级蜜罐docker一键启动

智云-一个抓取web流量的轻量级蜜罐docker安装教程 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN docker快速启动(v1.4) git clone https://github.com/xiaoxiaoranxxx/POT-ZHIYUN.git cd POT-ZHIYUN docker-compose up -d默认映射到80和8080端口 mysql不对外开放…...

原生HTML5、CSS、JavaScript实现简易网易云音乐播放

1.效果图 2.源码 1.index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>网易云音乐</title><link rel"stylesheet" href"../CSS/index.css"> </head>…...

网上商城小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商品信息管理&#xff0c;商品类型管理&#xff0c;活动专区管理&#xff0c;新品上架管理&#xff0c;用户评价管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包…...

微分方程(Blanchard Differential Equations 4th)中文版Section2.2

动力系统的几何分析 捕食者-猎物系统的向量场 在第2.1节中&#xff0c;我们展示了两个不同捕食者-猎物系统的 R ( t ) R(t) R(t) 和 F ( t ) F(t) F(t) 图形&#xff0c;但没有描述我们是如何生成这些图形的。我们将在第2.5节中解决这个问题&#xff0c;采用欧拉方法推广到…...

Swift 环境搭建

Swift 环境搭建 Swift 是由苹果公司开发的一种强类型编程语言&#xff0c;用于iOS、macOS、watchOS和tvOS应用程序的开发。搭建Swift开发环境是开始使用Swift进行编程的第一步。本文将详细介绍如何在不同的操作系统上搭建Swift开发环境。 在macOS上搭建Swift环境 系统要求 …...

科技与出版

科技与出版 ISSN: 1005-0590 CN: 11-3209/G3 常设栏目&#xff1a;特别策划、产业观察、融媒之光、编辑实务、营销方略、学术探索、创作空间等。 稿件要求 (1)来稿应有创新性&#xff1b;立论科学&#xff0c;主题明确&#xff0c;推理严谨&#xff1b;词语准确&#xff0c;…...

5年前端面试之路

作者&#xff1a;星空海绵 顺便吆喝一声&#xff0c;技术大厂&#xff0c;内推捞人&#xff0c;前/后端or测试←感兴趣 --加班偶尔较多&#xff0c;但周末加班两倍工资。 --15-35K&#xff0c;工资一线城市属于一般&#xff0c;但二线城市很可以。 前言 由于公司要进行&#xf…...

网站怎么做才能上百度首页/友情链接联盟

Hibernate中进行数据库增删改的代码&#xff0c;太多不想背了&#xff0c;记在这里以后来查好啦~~~~packageorg.lxh.hibernate.demo01;importjava.util.Iterator;importjava.util.List;importorg.hibernate.Query;importorg.hibernate.Session;importorg.hibernate.SessionFact…...

做学校后台网站/找网站设计公司

awesome-view 项目地址&#xff1a;xinghongfei/awesome-view 简介&#xff1a;自定义 View 有这些足够了 更多&#xff1a;作者 提 Bug 标签&#xff1a; 自定义view- 自定义 View 主要掌握以下四块内容&#xff1a; 绘制机制&#xff1a;掌握 onMeasure,onLayout,…...

中企动力邮箱登陆首页/成都优化官网公司

上周&#xff0c;Mike和我们分享了他在数据库设计方面的部分经验和SQL的一些注意点。 一、数据库设计 1&#xff0e;树形结构数据 &#xff1a;分为邻接模型和 物化路径模型 1.1树形数据&#xff0c;需要解决的问题是&#xff1a; 如何将数据高效地以树形的形式展现给用户&…...

wordpress修改成中文/网站制作公司咨询

大家好&#xff0c;我是脚丫先生 (o^^o) 说起&#xff0c;android&#xff0c;这是多么遥远的英文单词。 「第一行代码」 我想学过android开发的小伙伴都应该读过&#xff0c;可谓是入门神作。 看着郭霖大佬的大作&#xff0c;此刻&#xff0c;有那么带点陌生而又带一丝熟悉…...

网站设计费用多少/营业推广是一种什么样的促销方式

Gitlab库已损坏前端显示500错误解决方法参考文章&#xff1a; &#xff08;1&#xff09;Gitlab库已损坏前端显示500错误解决方法 &#xff08;2&#xff09;https://www.cnblogs.com/zhanmeiliang/p/7298188.html 备忘一下。...

2010网站建设管理/优化设计

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid6396 假设k为5&#xff0c;那么开5个数组用来分别存放每头怪兽对应的五个防御力 用五个指针去从头开始遍历&#xff0c;如果当前值小于对应的攻击力&#xff0c;就判断一下这头怪兽的五个值是不是都小于其对应…...