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


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

    一.简介

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

    二.命令模式

    命令模式(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());
    	}
    }
    

    六.运行结果

    七.源代码下载

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

  • 相关阅读:
    halcon算子翻译——close_framegrabber
    switch case 注意事项+1 及 case合并综合练习例子
    switch case 注意事项
    switch case
    equals()方法 与 == 区别
    if else 选择机构 _多重if选择机构_if选择结构嵌套(综合练习题——code)
    程序流程控制三大结构
    国外著名java论坛(FQ也要看!)
    键盘接收用户输入案例1——计算两数和
    键盘接收用户输入案例2(案例内容包含键盘接收 int、String、Char、double、boolean)等类型及介绍
  • 原文地址:https://www.cnblogs.com/miaowulj/p/11875414.html
Copyright © 2020-2023  润新知