如何在java中解耦数据和行为对象?

时间:2017-06-20 13:17:56

标签: java oop class-design

我正在使用Java为服务器构建多人游戏。目前,我使用单个类文件来存储播放器数据并处理数据。我是初学者,所以我不知道这是一个不好的做法。 http://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/这篇文章帮助我理解我违反了“单一责任原则”的规则。

这就是我的代码现在的样子。

public class PlayerSession{

    String playerId;
    String playerName;

    // 20+ player data fields, which I am trying to reduce
    // and keep only the most used data

    public void messageProcessor(JSONObject clientRequest) throws JSONException{

        switch(clientRequest.getString("task")){            
        case "login": loginProcess(); break;
        case "logout": logoutProcess(); break;

        //50+ different actions 
        }
    }

    public void populateSessionData(String playerId){
        // populate player data from database
    }

    private void loginProcess(){
        //Process login
    }

    private void logoutProcess(){
        //Process logout
    }

    //20+ other methods which do entirely different tasks.
}

随着我们添加更多功能,该类将变得极难维护和修改。现在我试图将这个类分成两个不同的类。一,仅存储播放器数据,另一个处理行为,如下所示。

public class PlayerSession {

    final TaskHandler taskHandler = new TaskHandler();

    public void messageProcessor(JSONObject clientRequest) throws JSONException {

        switch (clientRequest.getString("task")) {
        case "login":
            taskHandler.loginProcess();
            break;
        case "logout":
            taskHandler.logoutProcess();
            break;

        // 50+ different actions
        }
    }
}

public class PlayerData {

    String playerId;
    String playerName;

    // 20+ player data fields, which I am trying to reduce
    // and keep only the most used data

    public void populateSessionData(String playerId) {
        // populate player data from database
    }
}

public class TaskHandler {

    final PlayerData player = new PlayerData();

    private void loginProcess() {
        // Process login
    }

    private void logoutProcess() {
        // Process logout
    }

    // 20+ other methods which do entirely different tasks.
}

这种设计为单个客户端创建了另外两个对象,即PlayerData和TaskHandler。对于10,000个并发客户端的服务器,这会成为一个问题吗?这是正确的方法吗?如果没有,这样的场景的最佳方法是什么?

在某处我读到只是为了保存数据的对象不是一个好方法。是吗?

2 个答案:

答案 0 :(得分:0)

你需要在这里做很多事情:

PlayerSession类:

为什么要解析JsonObject?你需要创建一个名为ClientRequest的类,所有工作都将在其中完成。将您需要的所有内容从客户端请求放到此类中,只有那些准备使用某些的方法不会从对象中提取数据并在您的代码中手动计算这是程序方式。同时将PlayerSession重命名为Session

PlayerData类

首先将其重命名为Player类,它代表玩家不要播放器数据。不要在Player中执行任何数据库关系操作。同样在创建之后你需要准备好使用Player,在这里创建实例,然后用数据填充它,最好在构造函数中完成。

TaskHandler类

不要创建做很多事情的类,几乎以正确的方式创建类,简单的创建界面TaskAction只有一个方法performTask()并创建许多实现为LoginTask, LogoutTask等。也许你需要为你提供特定操作实例的结构,这有助于摆脱手动创建具体实现,你将以更多态的方式进行。

public class Session {

    private final SessionActions actions;
    private final RequestFabric requests;
    private final Player player;

    public Session (SessionActionFabric actionsFabric,
                    RequestFabric requests, Player player) {
        this.actionsFabric = actionsFabric;
        this.requests = request;
        this.player = player;
    }

    void login() throws LoginException {
        Request request = request.createRequest();
        SessionAction login = actions.createActions("login", player, request);
        login.performAction();
        //something like that it's depends on whole picture of your project and maybe changed
    }

    //etc.
}

public interface Request {

    public performRequest(Player player, /*request data your api specs here*/) throws RequestException;
}

public class Player {

    private String id;
    private String name;

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

   //getters, setters 
}

interface SessionAction {

    void performAction() throws SessionActionException;
}

class LoginAction implements SessionAction {
    private final Player player;
    private final Request request;


    LoginAction (Player player, Request request) {
        this.player = player;
        this.request = request;
    }

    void performAction() {
        // do you things here
    }

}

对于10,000个并发客户端的服务器,这会成为一个问题吗?这是正确的方法吗?如果没有,这样的场景的最佳方法是什么?

A 不要考虑性能最好注意好的设计,如果你遇到性能方面的问题,你几乎总能找到通过良好的设计(缓存,汇集等)改进性能的方法。)

我在某处读到了保存数据的对象不是一个好方法。是吗?

A 你是正确的,这称为贫血模型,(处理它的数据和方法是分开的),但目前它非常受欢迎。

答案 1 :(得分:0)

根据您与Joy的讨论。如果您担心像LoginAction这样的Action类将每2秒创建一次。使用单例模式,具有动作类的静态最终实例和该实例的一个静态getter(LoginAction.getInstanceOfLoginAction())并且每次都使用它而不是创建新的。但请确保您的行动课程是无国籍的,而不是有状态的!

class LoginAction implements SessionAction {
  private static final LoginAction loginAction = new LoginAction();
  public static LoginAction getLoginAction() {
      return loginAction;
  }

  void performAction(Player player, Request request) {
    // do you things here
  }

}

还有一件事使用工厂(参见工厂模式)来按要求获得Action接口的实现。