从王者荣耀看设计模式(九.命令模式)

从王者荣耀看设计模式(命令模式)

一.简介

王者荣耀是一款团队竞技游戏。良好的团队信息交流在一定程度上能帮助队伍取得胜利。为了保证游戏的流畅性与便捷性,王者荣耀提供了快捷交流机制,在王者小地图旁边有几个快捷聊天按钮(开始撤退,发起进攻,请求结合),玩家可通过点击快捷聊天按钮发出相应命令与队友进行交流

二.命令模式

命令模式(Command Pattern):命令模式是一种高内聚的模式,将"请求"封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

  • 命令模式的使用场景

    1. 只要你认为是命令的地方就可以采用命令模式,例如,在GUI开发中,一个按钮的点击就是一个命令,可以采用命令模式;模拟DOS命令的时候,当然也要采用命令模式:触发-反馈机制的处理等。
    2. 解决命令的请求者和命令的实现者之间的耦合关系。
  • 命令模式涉及的设计原则有:
  1. 每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
  2. 请求方和接收方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
  3. 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
  • 命令模式的通用类图:
  • 命令模式所涉及的角色有:
    抽象命令(Command):定义命令的接口,声明执行的方法。
    具体命令(ConcreteCommand):具体命令,实现要执行的方法,它通常是“虚”的实现;通常会有接收者,并调用接收者的功能来完成命令要执行的操作。
    接收者(Receiver):真正执行命令的对象。任何类都可能成为一个接收者,只要能实现命令要求实现的相应功能。
    调用者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
    客户端(Client):命令由客户端来创建,并设置命令的接收者。
    ---
  • 命令模式的优点:
    1. 类间解耦:调用者角色与接受者角色之间没有任何依赖关系,调用者实现功能时只需调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行
    2. 可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
    3. 命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command子类的膨胀问题。
  • 命令模式的缺点:
    命令模式也是优缺点的,请看Command子类:如果有N个命令,问题就出来了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大

三.结构图

四.设计类图

五.代码实现

com.practice.ObserverModule包内容结合自从王者荣耀看设计模式(观察者模式)
Observerable(抽象被观察者接口)

package com.practice.ObserverModule;
/***
 * 抽象被观察者接口
 * 声明了添加、删除、通知观察者方法
 *
 */

public interface Observerable {
    public void RegisterObserver(Observer o);
    public void RemoveObserver(Observer o);
    public void NotifyObserver();
}

InformMessage类(被观察者类)

package com.practice.ObserverModule;

import java.util.ArrayList;
import java.util.List;

/*
 * 被观察者
*实现了Observerable接口,对Observerable接口的三个方法进行了具体实现
 *
 */
public class InformMessage implements Observerable {
    private String message;
    private String heroName;
    private List<Observer> list;

    public InformMessage() {
        list = new ArrayList<Observer>();
    }

    public void NotifyObserver() {
        for(int i = 0;i < list.size(); i++) {
            Observer observer = list.get(i);
            observer.update(message);
        }
    }

    public void RegisterObserver(Observer o) {
        list.add(o);

    }

    public void RemoveObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    public void setInformation(String name,Observer o,String message) {
        this.message = message;
        this.heroName = name;
        System.out.println("英雄[" + heroName + "]发出消息:" + message);
        RemoveObserver(o);
        NotifyObserver();
        list.add(o);
    }
}

Observer类(抽象观察者类)

package com.practice.ObserverModule;

/*
 * 抽象观察者
 * 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。
 */

public interface Observer {
    public void update(String message);
}

Hero类(观察者类)

package com.practice.ObserverModule;
/**
 * 观察者
 * 实现了update方法
 *
 */
public class Hero implements Observer{
    private String name;
    private String message;

    public Hero(String heroName) {
        this.name = heroName;
    }

    public void update(String message) {
        this.message = message;
        read();
    }

    public void read() {
        System.out.println(name + "收到消息:" + message);
    }
}

GameInform类(接收类)

package com.practice.OrderModule;

/*
 * 接收类
 */

public class GameInform {
    public String Attack() {
        return "发起进攻";
    }

    public String Retreat() {
        return "开始撤退";
    }

    public String Gather() {
        return "请求集合";
    }
}

Command类(抽象命令角色类)

package com.practice.OrderModule;

/*
 * 抽象命令角色类
 */

public interface Command {
    public String execute();
}

AttackCommand类(具体角色类)

package com.practice.OrderModule;

/*
 * 具体角色类
 */

public class AttackCommand implements Command{
    private GameInform gameInform;

    public AttackCommand(GameInform gameInform) {
        this.gameInform = gameInform;
    }

    public String execute() {
        return gameInform.Attack();
    }
}

RetreatCommand类(具体角色类)

package com.practice.OrderModule;

/*
 * 具体角色类
 */

public class RetreatCommand implements Command{
    private GameInform gameInform;

    public RetreatCommand(GameInform gameInform) {
        this.gameInform = gameInform;
    }

    public String execute() {
        return gameInform.Retreat();
    }

}

GatherCommand类(具体角色类)

package com.practice.OrderModule;

/*
 * 具体角色类
 */

public class GatherCommand implements Command{
    private GameInform gameInform;

    public GatherCommand(GameInform gameInform) {
        this.gameInform = gameInform;
    }

    public String execute() {
        return gameInform.Gather();
    }
}

Keypad类(请求角色类)

package com.practice.OrderModule;

/*
 * 请求角色类
 */

public class Keypad {
    private Command AttackCommand;
    private Command RetreatCommand;
    private Command GatherCommand;

    public void setAttackCommand(Command AttackCommand) {
        this.AttackCommand = AttackCommand;
    }

    public void setRetreatCommand(Command RetreatCommand) {
        this.RetreatCommand = RetreatCommand;
    }

    public void setGatherCommand(Command GatherCommand) {
        this.GatherCommand = GatherCommand;
    }

    public String Attack() {
        return AttackCommand.execute();
    }

    public String Retreat() {
        return RetreatCommand.execute();
    }

    public String Gather() {
        return GatherCommand.execute();
    }
}

Test类(测试类)

package com.practice.Test;

import com.practice.ObserverModule.Hero;
import com.practice.ObserverModule.InformMessage;
import com.practice.ObserverModule.Observer;
import com.practice.OrderModule.AttackCommand;
import com.practice.OrderModule.Command;
import com.practice.OrderModule.GameInform;
import com.practice.OrderModule.GatherCommand;
import com.practice.OrderModule.Keypad;
import com.practice.OrderModule.RetreatCommand;

public class Test {
    public static void main(String [] args) {
        //首先创建被观察者对象
        InformMessage HeroGlory = new InformMessage();
        //创建接收者对象
        GameInform gameInform = new GameInform();

        //将接收者对象传入命令对象
        Command attackCommand = new AttackCommand(gameInform);
        Command retreatCommand = new RetreatCommand(gameInform);
        Command gatherCommand = new GatherCommand(gameInform);

        //创建请求者对象
        Keypad keypad = new Keypad();
        //把命令传给请求者
        keypad.setAttackCommand(attackCommand);
        keypad.setRetreatCommand(retreatCommand);
        keypad.setGatherCommand(gatherCommand);

        //创建观察者对象
        Observer HanXin = new Hero("韩信");
        Observer HouYi = new Hero("后羿");
        Observer DianWei = new Hero("典韦");
        Observer DaJi = new Hero("妲己");
        Observer LiuShan = new Hero("刘禅");

        //添加观察者
        HeroGlory.RegisterObserver(HanXin);
        HeroGlory.RegisterObserver(HouYi);
        HeroGlory.RegisterObserver(DianWei);
        HeroGlory.RegisterObserver(DaJi);
        HeroGlory.RegisterObserver(LiuShan);

        //1.更新消息 2.调用请求
        HeroGlory.setInformation("妲己",DaJi,keypad.Retreat());

        System.out.println("---------------------------------------------------");
        HeroGlory.setInformation("后羿",HouYi,keypad.Gather());
    }
}

运行结果

原文地址:https://www.cnblogs.com/miaowulj/p/11875414.html

时间: 2024-08-24 19:34:14

从王者荣耀看设计模式(九.命令模式)的相关文章

从王者荣耀看设计模式(虚拟代理模式)

从王者荣耀看设计模式(虚拟代理模式) 一.简介 王者荣耀游戏设置了很多种游戏模式,比如:王者模拟战.无限乱斗.梦境大乱斗.火焰山大战等.当从王者荣耀的主界面进入各类模式的界面时,由于网络原因,会存在一定程度的延时(会有一个圈圈在主界面一直转啊转啊转(??へ??╬)),直到加载完图片,会跳转到各模式界面. 二.虚拟代理(作为创建开销大的对象的代表) 虚拟代理是作为创建开销大的对象的代表.虚拟代理经常直到我们真正需要一个对象的时候才创建它.当对象在创建前和创建中时,由虚拟代理来扮演对象的替身.对象创

从王者荣耀看设计模式(十四.工厂方法模式)

从王者荣耀看设计模式(工厂方法模式) 二.简介 王者荣耀游戏设计师根据英雄技能.属性.天赋等因素,将英雄划分为射手.辅助.打野.法师.坦克.战士等职业.一局比赛存在多类英雄可供选择.玩家在挑选游戏英雄时,合理的英雄职业搭配是赢得游戏胜利的基本保证. 三.工厂方法模式 工厂方法模式(Factory Method Pattern):工厂方法模式又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式.在

从王者荣耀看设计模式(十七.原型模式)

从王者荣耀看设计模式(原型模式) 一.简介 王者荣耀包含有很多的玩法,其中有一种游戏模式只在周六和周日开放,那就是--克隆模式.与常规的游戏双方阵营只允许出现单一英雄不同,在克隆模式中,双方各选择一个英雄进行克隆,换句话说,一个阵营的五个人操作的五个相同的英雄 二.模式动机 在软件系统中,有些对象的创建过程比较复杂,而且有时候需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在. 三.原型模式 原型模式

从王者荣耀看设计模式(保护代理模式)

从王者荣耀看设计模式(保护模式) 一.简介 打开王者荣耀,点击右上角头像标志可进入我的信息主页.在我的个人主页中,我可以可设置玩家的游戏昵称,性别,常用英雄.除此之外,我还可以查看自己得到别人点赞的次数(不能给自己点赞);其他玩家亦可访问我的主页,可以给我点赞,可以查看我设置的所有信息(不能更改). 二.保护代理(控制用户的访问权限) 保护代理,是提供某些级别的保护,根据客户的权限和决定客户可否访问哪些特定的方法,所以保护代理可能只提供给客户部分接口. 三.Java动态代理 Java在java.

从王者荣耀看设计模式(十六.建造者模式)

从王者荣耀看设计模式(建造者模式) 一.简介 为了玩王者荣耀的游戏体验感,不少玩家都会选择花钱购买自己常用英雄的皮肤.一方面,购买的皮肤通常要比原画更加"炫酷".另一方面,购买的英雄皮肤常常伴随有特殊的回城特效与攻击技能特效. 二.模式动机 不管在生活中还是软件系统中,都存在一个包含多个组成部件的复杂对象,如汽车,它包括车轮.方向盘.发动机等各种部件.组成复杂对象的这些部件之间或许还会一定的约束,若某些属性没有赋值可能无法构成完整产品使用.如,电子邮件包含地址.收件人姓名.联系方式.创

从王者荣耀看设计模式(二十一.中介者模式)

从王者荣耀看设计模式(中介者模式) 一.简介 在王者荣耀中,有一个简单的聊天室,在聊天室中.玩家点击综合可以与全服的玩家发送消息,点击好友可向指定好友玩家私发信息.|??ω?` ) 二.模式动机 联合国是一个协调组织,各个国家就一些共同问题经由联合国进行协商,它取代了原本各个国家之间的直接交流,将各个成员国之间的强耦合关系转换为较为松散的耦合关系.在软件开发中,我们有时候也会需要使用类似联合国一样的中间对象来降低系统中类与类,对象与对象之间的耦合关系. 在本实例中,玩家与玩家多对多的通信,导致用

设计模式之命令模式

命令模式的核心是把方法调用封装起来,调用的对象不需要关心是如何执行的. 定义:命令模式将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也可以支持撤销操作. 先看一个例子,设计一个家电遥控器的API,可以通过遥控器发出命令来控制不同生产商生产的家电,比如关灯.开灯. 以下是一个简单的代码示例. 1 package cn.sp.test05; 2 /** 3 * 电灯类 4 * @author 2YSP 5 * 6 */ 7 public class Lig

用Java 8 Lambda表达式实现设计模式:命令模式

链接:http://www.importnew.com/16789.html 在这篇博客里,我将说明如何在使用Java 8 Lambda表达式的函数式编程方式时实现命令设计模式.命令模式的目标是将请求封装成一个对象,从对客户端的不同类型请求,例如队列或日志请求参数化,并提供相应的操作.命令模式是一种通用编程方式,该方式基于运行时决策顺序来执行方法.模式的参与者如下: 命令 :声明用于执行操作的接口. 实体命令 :定义接收者对象和动作的绑定. 客户端 :创建实体命令实例并设置它的接收者. 调用者:

设计模式 7 —— 命令模式

设计模式目录: 设计模式 1 ——观察者模式 设计模式 2 —— 装饰者模式 设计模式 3 —— 迭代器和组合模式(迭代器) 设计模式 4 —— 迭代器和组合模式(组合) 设计模式 5 —— 工厂模式 设计模式 6 —— 单件模式 设计模式 7 —— 命令模式 概述 第1部分 问题引入 第2部分 定义和实现 第3部分 使用宏命令 第1部分 问题引入 首先看下,下面的要求: 实现命令接口 首先,让说有的命令对象实现相同的包含一个方法的接口. 1 /** 2 * 命令接口 3 * @ClassNam