从王者荣耀看设计模式(九.命令模式)
Posted miaowulj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从王者荣耀看设计模式(九.命令模式)相关的知识,希望对你有一定的参考价值。
从王者荣耀看设计模式(命令模式)
一.简介
王者荣耀是一款团队竞技游戏。良好的团队信息交流在一定程度上能帮助队伍取得胜利。为了保证游戏的流畅性与便捷性,王者荣耀提供了快捷交流机制,在王者小地图旁边有几个快捷聊天按钮(开始撤退,发起进攻,请求结合),玩家可通过点击快捷聊天按钮发出相应命令与队友进行交流
二.命令模式
命令模式(Command Pattern):命令模式是一种高内聚的模式,将"请求"封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
- 命令模式的使用场景
- 只要你认为是命令的地方就可以采用命令模式,例如,在GUI开发中,一个按钮的点击就是一个命令,可以采用命令模式;模拟DOS命令的时候,当然也要采用命令模式:触发-反馈机制的处理等。
- 解决命令的请求者和命令的实现者之间的耦合关系。
- 命令模式涉及的设计原则有:
- 每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
- 请求方和接收方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
- 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。
命令模式的通用类图:
命令模式所涉及的角色有:
抽象命令(Command):定义命令的接口,声明执行的方法。
具体命令(ConcreteCommand):具体命令,实现要执行的方法,它通常是“虚”的实现;通常会有接收者,并调用接收者的功能来完成命令要执行的操作。
接收者(Receiver):真正执行命令的对象。任何类都可能成为一个接收者,只要能实现命令要求实现的相应功能。
调用者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
客户端(Client):命令由客户端来创建,并设置命令的接收者。
---- 命令模式的优点:
- 类间解耦:调用者角色与接受者角色之间没有任何依赖关系,调用者实现功能时只需调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行
- 可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少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());
}
}
运行结果
以上是关于从王者荣耀看设计模式(九.命令模式)的主要内容,如果未能解决你的问题,请参考以下文章