首页 > 其他分享 >手游后端架构中,用命令模式解决什么问题

手游后端架构中,用命令模式解决什么问题

时间:2024-09-04 14:55:27浏览次数:11  
标签:架构 String 手游后 模式 玩家 client println public out

Hello,大家好,我是 V 哥。命令模式(Command Pattern)是一种行为设计模式,它将一个请求封装为一个对象,从而允许用户使用不同的请求、队列或日志请求来参数化其他对象。命令模式也支持可撤销的操作。在手游后端架构中,

  1. 命令模式可以将玩家的操作请求(如移动、攻击、技能释放等)封装成对象,这些对象可以被存储在队列中,以便按顺序处理。

  2. 通过命令模式,可以将发起操作的对象(发送者)和执行操作的对象(接收者)分离,使得系统更加模块化,易于扩展和维护。

  3. 在游戏中,玩家可能会犯错或需要撤销之前的行动。命令模式可以轻松实现操作的撤销和重做功能。

  4. 命令模式可以将操作封装为对象,这些对象可以异步执行,不会阻塞主线程,提高游戏的响应性和性能。

  5. 在游戏中,一个玩家的行为可能会影响其他玩家或游戏环境。命令模式可以将这些行为封装为命令对象,并通过事件系统广播给所有受影响的实体。

  6. 在多人游戏中,命令模式可以管理玩家之间的协同操作,确保操作的一致性和顺序性。

  7. 游戏中的资源(如金币、道具等)的分配和回收可以通过命令模式来管理,确保资源操作的原子性和一致性。

  8. 在网络游戏中,命令模式可以用于封装网络请求和响应,简化网络通信逻辑。

还有更多具体的问题可以解决,你是不是觉得命令模式原来可以这么强大呀,当然命令模式通常与其他设计模式结合使用,如策略模式、观察者模式、状态模式等,以构建一个灵活、可扩展和易于维护的系统。

接下来,上案例喽。

创建一个完整的手游后端服务端示例涉及到许多组件,包括网络通信、数据库交互、业务逻辑处理等。在这里,我将提供一个非常简化的示例,它模拟了一个基本的游戏后端服务,包括玩家注册、登录和获取玩家信息的功能。这个示例将使用Java的Socket编程来处理客户端请求。

注意:这个示例仅用于教学目的,实际的手游后端会更加复杂,需要考虑安全性、并发性、数据库存储、错误处理等多个方面。

首先,我们需要一个Player类来表示玩家:

public class Player {
    private String id;
    private String username;
    private String password;

    public Player(String id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    // Getters and setters
    public String getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

接下来,我们创建一个PlayerService类来处理玩家相关的业务逻辑:

import java.util.HashMap;
import java.util.Map;

public class PlayerService {
    private Map<String, Player> players = new HashMap<>();

    public synchronized String registerPlayer(String username, String password) {
        String playerId = Integer.toString(players.size() + 1);
        players.put(playerId, new Player(playerId, username, password));
        return playerId;
    }

    public synchronized Player login(String username, String password) {
        for (Player player : players.values()) {
            if (player.getUsername().equals(username) && player.getPassword().equals(password)) {
                return player;
            }
        }
        return null;
    }

    public synchronized Player getPlayer(String playerId) {
        return players.get(playerId);
    }
}

然后,我们创建一个GameServer类来处理网络连接和请求:

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class GameServer {
    private ServerSocket serverSocket;
    private final int PORT = 12345;
    private PlayerService playerService = new PlayerService();

    public void startServer() {
        try {
            serverSocket = new ServerSocket(PORT);
            System.out.println("Game server is running on port " + PORT);

            while (true) {
                Socket socket = serverSocket.accept();
                new Handler(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class Handler extends Thread {
        private Socket socket;
        private BufferedReader in;
        private PrintWriter out;

        public Handler(Socket socket) {
            this.socket = socket;
            try {
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out = new PrintWriter(socket.getOutputStream(), true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void run() {
            try {
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    System.out.println("Received: " + inputLine);
                    if ("REGISTER".equals(inputLine)) {
                        String playerId = playerService.registerPlayer("username", "password");
                        out.println("REGISTERED " + playerId);
                    } else if ("LOGIN".equals(inputLine)) {
                        Player player = playerService.login("username", "password");
                        if (player != null) {
                            out.println("LOGIN_SUCCESS " + player.getId());
                        } else {
                            out.println("LOGIN_FAILURE");
                        }
                    } else if ("GET_PLAYER".equals(inputLine)) {
                        String[] parts = inputLine.split(" ", 2);
                        if (parts.length == 2) {
                            Player player = playerService.getPlayer(parts[1]);
                            if (player != null) {
                                out.println("PLAYER " + player.getId() + " " + player.getUsername());
                            } else {
                                out.println("PLAYER_NOT_FOUND");
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        GameServer server = new GameServer();
        server.startServer();
    }
}

GameServer类创建了一个服务器套接字,并监听指定的端口。每当有新的客户端连接时,它都会创建一个新的Handler线程来处理该连接。Handler线程读取客户端发送的命令,并根据命令执行相应的操作,如注册玩家、登录或获取玩家信息。

以上演示了最基本的文本协议来进行通信,客户端和服务器之间通过读取和发送字符串来交互。当然你也可以使用更加复杂的协议,比如 JSONProtocol Buffers等,看你的需求,这里是为了简化演示逻辑哈。

要运行这个示例,你需要创建一个客户端来连接到服务器并发送命令。客户端可以使用任何支持网络通信的编程语言编写。

下面是一个 Java 客户端代码示例,它将连接到服务器并发送一些命令来注册玩家、登录并获取玩家信息。这个客户端将使用 GameServer 示例中定义的相同协议。

import java.io.*;
import java.net.Socket;

public class GameClient {
    private Socket socket;
    private PrintWriter out;
    private BufferedReader in;

    public GameClient(String serverAddress, int port) {
        try {
            socket = new Socket(serverAddress, port);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendCommand(String command) {
        out.println(command);
    }

    public String readResponse() {
        try {
            return in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void close() {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        GameClient client = new GameClient("localhost", 12345);

        // 注册玩家
        client.sendCommand("REGISTER");
        String registerResponse = client.readResponse();
        System.out.println("Register response: " + registerResponse);

        // 登录玩家
        client.sendCommand("LOGIN");
        String loginResponse = client.readResponse();
        System.out.println("Login response: " + loginResponse);

        // 获取玩家信息
        String[] loginParts = loginResponse.split(" ", 2);
        if (loginParts.length == 2 && "LOGIN_SUCCESS".equals(loginParts[0])) {
            client.sendCommand("GET_PLAYER " + loginParts[1]);
            String playerResponse = client.readResponse();
            System.out.println("Player info response: " + playerResponse);
        }

        // 关闭连接
        client.close();
    }
}

我们首先创建了一个 GameClient 实例,指定服务器的地址和端口。然后,我们使用 sendCommand 方法发送命令到服务器,并使用 readResponse 方法读取服务器的响应。

main 方法中,我们执行以下步骤:

  1. 发送 “REGISTER” 命令以注册新玩家,并读取响应。
  2. 检查注册响应是否表示成功,并提取玩家 ID。
  3. 使用 “LOGIN” 命令登录玩家,并读取响应。
  4. 检查登录响应是否表示成功,并提取玩家 ID。
  5. 使用 “GET_PLAYER” 命令和玩家 ID 获取玩家信息,并读取响应。
  6. 检查玩家信息响应,并打印玩家的 ID 和用户名。
  7. 最后,关闭与服务器的连接。

代码是这样的:

下面是 GameClient 类中 main 方法的完整测试代码,它将连接到服务器并发送一系列命令来演示注册、登录和获取玩家信息的过程:

public static void main(String[] args) {
    // 创建客户端实例,连接到服务器
    GameClient client = new GameClient("localhost", 12345);

    // 注册玩家
    client.sendCommand("REGISTER");
    String registerResponse = client.readResponse();
    System.out.println("Register response: " + registerResponse);

    // 假设注册成功,服务器会返回 REGISTERED 后跟玩家ID
    if (registerResponse.startsWith("REGISTERED")) {
        String playerId = registerResponse.substring("REGISTERED ".length());
        System.out.println("Registered player ID: " + playerId);

        // 登录玩家
        client.sendCommand("LOGIN");
        String loginResponse = client.readResponse();
        System.out.println("Login response: " + loginResponse);

        // 假设登录成功,服务器会返回 LOGIN_SUCCESS 后跟玩家ID
        if (loginResponse.startsWith("LOGIN_SUCCESS")) {
            String loggedInPlayerId = loginResponse.substring("LOGIN_SUCCESS ".length());
            System.out.println("Logged in player ID: " + loggedInPlayerId);

            // 获取玩家信息
            client.sendCommand("GET_PLAYER " + loggedInPlayerId);
            String playerResponse = client.readResponse();
            System.out.println("Player info response: " + playerResponse);

            // 假设获取玩家信息成功,服务器会返回 PLAYER 后跟玩家ID和用户名
            if (playerResponse.startsWith("PLAYER")) {
                String[] playerInfo = playerResponse.split(" ", 3);
                if (playerInfo.length == 3) {
                    System.out.println("Player ID: " + playerInfo[1]);
                    System.out.println("Player Username: " + playerInfo[2]);
                } else {
                    System.out.println("Error: Invalid player info format.");
                }
            } else {
                System.out.println("Error: Failed to get player info.");
            }
        } else {
            System.out.println("Error: Login failed.");
        }
    } else {
        System.out.println("Error: Registration failed.");
    }

    // 关闭连接
    client.close();
}

完事儿。以上就是本文的全部内容笔记,感谢老铁们的支持和鼓励,不当之处还请不吝赐教,欢迎关注威哥爱编程,努力的人相信总会有回报。

标签:架构,String,手游后,模式,玩家,client,println,public,out
From: https://blog.csdn.net/finally_vince/article/details/141893956

相关文章

  • 51单片机 - 定时器0(按键控制LED流水灯模式)
    时间:2024.9.2目的:手撕51作者:Whappy定时器0寄存器配置1.定时器0配置过程首先要配置定时器的寄存器TCON和TMOD使计数器开始计数及定时器的初始值,配置使这个链路连起来。#include<REGX52.H>voidTimer0_Init(){ TMOD=0x01;//工作模式寄存器 //控制寄存器 TF......
  • LNMP架构
    1. 依据网站类型来考虑网站运行起来的环境:网站开发的语言JAVA:LNMT(linuxnginxmysqltomcat)PHP:(参考zabbix)LNMP,把网站的代理放到网页根目录下Python:LNMU(UWSGI)2. 项目部署:1-1 项目类型(项目的开发语言)1-2 项目运行平台的技术选择1-3 尽快让项目运行起来——ALLINONE......
  • 数字人直播阿凡达模式2.0版本揭秘:灰豚运用了哪些黑技术?
    随着数字人直播的应用频率不断提升,其在帮助企业降本增效方面的潜力也随之显现,刺激市场需求的同时,也让用户对它的期待值持续增长。在此背景下数字人源码厂商开始不断加大研发力度,以推动数字人直播技术的持续升级,数字人直播阿凡达模式2.0版本的上线便是典型案例之一。本期,小编......
  • 掌握检索技术:构建高效知识检索系统的架构与算法12
    在检索专业知识层需要涵盖更高级的检索技术,包括工程架构和算法策略。一、工程架构工程架构在构建检索系统中决定了系统的可扩展性、高可用性和性能。比如需要考虑的基本点:分布式架构:水平扩展:采用分布式架构,将检索任务分布到多个节点上,实现水平扩展。这可以通过将索引数据......
  • 掌握检索技术:构建高效知识检索系统的架构与算法29
    在检索专业知识层需要涵盖更高级的检索技术,包括工程架构和算法策略。一、工程架构工程架构在构建检索系统中决定了系统的可扩展性、高可用性和性能。比如需要考虑的基本点:分布式架构:水平扩展:采用分布式架构,将检索任务分布到多个节点上,实现水平扩展。这可以通过将索引数据......
  • 掌握检索技术:构建高效知识检索系统的架构与算法27
    在检索专业知识层需要涵盖更高级的检索技术,包括工程架构和算法策略。一、工程架构工程架构在构建检索系统中决定了系统的可扩展性、高可用性和性能。比如需要考虑的基本点:分布式架构:水平扩展:采用分布式架构,将检索任务分布到多个节点上,实现水平扩展。这可以通过将索引数据......
  • C#设计模式入门实战教程
    思维导航什么是设计模式设计模式的作用设计模式分类创建型模式(CreationalPatterns)结构型模式(StructuralPatterns)行为型模式(BehavioralPatterns)C#实现的设计模式示例代码推荐学习书籍项目源码地址优秀项目和框架精选什么是设计模式设计模式是对面向对象设计中......
  • MySQL5.7.36之高可用架构部署-MHA
    配置关键:程序软连接(所有节点)。因为MHA只能从/usr/bin中进行调用ln-s/application/mysql/bin/mysqlbinlog/usr/bin/mysqlbinlogln-s/application/mysql/bin/mysql/usr/bin/mysql1、配置互信(主库上操作)rm-rf/root/.sshssh-keygencd/root/.sshmvid_rsa.pub......
  • 设计模式-离线并发模式-隐含锁(Implicit Lock)
    作用允许框架或层超类型代码来获取离线锁锁机制应该由应用隐含的完成,而不是由开发人员编写代码完成,这样可以避免编写锁代码的疏忽而造成的数据不一致等情况。实现机制实现隐含锁就是要分解代码,在应用程序框架中完成那些无法逾越的锁机制。在悲观离线锁的任务中,会出现两......
  • 设计模式-粗粒度锁(Coarse-Grained Lock)
    作用用一个锁所住一组相关的对象粗粒度锁是覆盖多个对象的单个锁,这样不仅简化了加锁行为本身,而且让你不必为了给它们加锁所而加载所有的对象。运行机制实现粗粒度锁的第一步是为一组对象建立一个控制点,使得只用一个锁就能锁住多个对象。用乐观离线锁让组中每个对象都共享......