无废话C#设计模式之十八:Command

意图

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

场景

我们知道,网络游戏中的客户端需要不断把当前人物的信息发送到游戏服务端进行处理(计算合法性、保存状态到数据库等)。假设有这样一种需求,在服务端收到客户端的请求之后需要判断两次请求间隔是不是过短,如果过短的话就考虑可能是游戏外挂,不但不执行当前请求还要把前一次请求进行回滚。暂且把问题简单化一点不考虑客户端和服务端之间的通讯来进行程序设计的话,你可能会创建一个Man类型,其中提供了一些人物移动的方法,执行这些方法后,服务端内存中的人物会进行一些坐标的修改。客户端定时调用Man类型中的这些方法即可。那么如何实现防外挂的需求呢?你可能会想到在Man方法中保存一个列表,每次客户端调用方法的时候把方法名和方法调用的时间保存进去,然后在每个方法执行之前就进行判断。这样做有几个问题:

l Man类型应该只是负责执行这些操作的,是否应该执行操作的判断放在Man类型中是否合适?

l 如果方法的调用还有参数的话,是不是需要把方法名、方法的参数以及方法调用时间都保存到列表中呢?

l 如果需要根据不同的情况回滚一组行为,比如把Man类型的方法分为人物移动和装备损耗,如果客户端发送命令的频率过快希望回滚所有人物移动的行为,如果客户端发送命令的频率过慢希望回滚所有装备损耗的行为。遇到这样的需求怎么实现呢?

由此引入命令模式,命令模式的主要思想就是把方法提升到类型的层次,这样对方法的执行有更多的控制力,这个控制力表现在对时间的控制力、对撤销的控制力以及对组合行为的控制力。

时间: 2024-09-12 05:42:33

无废话C#设计模式之十八:Command的相关文章

无废话C#设计模式之十九:Observer

意图 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新. 场景 这次不说游戏了,假设我们需要在一个Web页面上分页显示数据.首先需要一个分页控制器和一个显示数据的表格.开始,客户的需求很简单,需要两个向前翻页向后翻页的按钮作为控制器,还需要一个GridView来显示数据.你可能会这么做: l 在页面上放两个按钮和一个GridView控件 l 点击了下一页按钮判断是否超出了页面索引,如果没有的话更新GridView中的数据,然后更新控件的当前

无废话C#设计模式之十四:Template Method

意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 场景 模版方法是非常容易理解的设计模式,一来是因为它没有过多结构上的交错,二来是因为这种代码复用技术对于掌握OO知识的人来说非常容易可以想到,很可能你已经在很多地方运用了模版方法.在运用一些设计模式的时候常常也会一起运用模版方法,甚至有的设计模式本身就带有模版方法的思想. 今天,我们给出这样一个实际的例子.做过银行支付.支付宝支付的人都知道,

无废话C#设计模式之十六:State

意图 允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类. 场景 我们在制作一个网上书店的网站,用户在书店买了一定金额的书后可以升级为银会员.黄金会员,不同等级的会员购买书籍有不同的优惠.你可能会想到可以在User类的BuyBook方法中判断用户历史消费的金额来给用户不同的折扣,在GetUserLevel方法中根据用户历史消费的金额来输出用户的等级.带来的问题有三点: l 不用等级的用户给予的优惠比率是经常发生变化的,一旦变化是不是就要修改User类呢? l 网站在初期可能最

无废话C#设计模式之十五:Strategy

意图 定义一系列的算法,把它们一个一个封装起来,并且使它们可相互替换.本模式使得算法可以独立于它的客户而变化. 场景 在开发程序的时候,我们经常会根据环境不同采取不同的算法对对象进行处理.比如,在一个新闻列表页面需要显示所有新闻,而在一个新闻搜索页面需要根据搜索关键词显示匹配的新闻.如果在新闻类内部有一个ShowData方法的话,那么我们可能会传入一个searchWord的参数,并且在方法内判断如果参数为空则显示所有新闻,如果参数不为空则进行搜索.如果还有分页的需求,那么还可能在方法内判断是否分

无废话C#设计模式之十二:Bridge

意图 将抽象部分与实现部分分离,使它们都可以独立的变化. 场景 还是说我们要做的网络游戏,多个场景需要扩充的问题我们已经采用了创建型模式来解决.现在的问题就是,不仅仅是游戏场景会不断扩充,而且游戏的模式也在不断扩充.比如,除了最基本的战斗模式之外,还会有道具模式,金币模式等. 对于这种在多个维度上都会有变化或扩充需求的项目来说,可以考虑引入桥接模式.或许你会说,不管是什么场景,不管什么模式,都可以是抽象场景的一个子类,但是,如果这样的话,4个场景和3种模式就会产生12个子类,而10个场景5种模式

无废话C#设计模式之十:Flyweight

意图 运用共享技术有效地支持大量细粒度的对象. 场景 在比较底层的系统或者框架级的软件系统中,通常存在大量细粒度的对象.即使细力度的对象,如果使用的数量级很高的话会占用很多资源.比如,游戏中可能会在无数个地方使用到模型数据,虽然从数量上来说模型对象会非常多,但是从本质上来说,不同的模型可能也就这么几个. 此时,我们可以引入享元模式来共享相同的模型对象,这样就可能大大减少游戏对资源(特别是内存)的消耗. 示例代码 using System; using System.Collections; us

云计算设计模式(十八)——重试模式

云计算设计模式(十八)--重试模式 启用应用程序来处理预期的,暂时的失败时,它会尝试连接到由透明的重试操作了以前失败的期望,失败的原因是瞬时的服务或网络资源.这种模式可以提高应用程序的稳定性. 背景和问题 该通信的应用程序与在云中运行的元素必须是可能发生在这样的环境中的瞬时故障敏感.这些故障包括网络连接的过程中出现时,一个服务是忙碌的瞬时损失的组件和服务中,服务的临时不可用,或超时. 这些故障一般是自校正的,如果经过一个合适的延迟被重复触发一个故障的动作很可能是成功的.例如,数据库服务,它正在处

无废话C#设计模式之二十二:总结(针对GOF23)

本文配套源码 比较 设计模式 常用程度 适用层次 引入时机 结构复杂度 Abstract Factory 比较常用 应用级 设计时 比较复杂 Builder 一般 代码级 编码时 一般 Factory Method 很常用 代码级 编码时 简单 Prototype 不太常用 应用级 编码时.重构时 比较简单 Singleton 很常用 代码级.应用级 设计时.编码时 简单 Adapter 一般 代码级 重构时 一般 Bridge 一般 代码级 设计时.编码时 一般 Composite 比较常用

无废话C#设计模式之二十:Mediator

意图 用一个中介对象来封装一系列对象的交互.中介者使得各对象不需要显式相互引用,从而使其松散耦合,而且可以独立地改变它们之间的交互. 场景 我们知道,一个网络游戏往往有很多大区.每一个大区可以是一组服务器,也可以是多组服务器,在这里假设一个大区是一组服务器.为了效率,一般每个大区都会有一个数据库,玩家的创建角色.充值.消费行为只是在这一个大区中有效.现在公司有了新的需求,那就是玩家的一些信息能在多个大区中共享.比如,在注册的时候就把玩家的账户信息写入多个信息共享的大区,玩家在某个大区中充值需要"