客户/服务器设计模式

时间:2016-10-10 13:42:21

标签: java design-patterns client-server

我是编程新手,我想编写一个简单的客户端服务器系统,客户端发送命令,如" SAY house"并且服务器检测到关键字" SAY"作为一个命令并返回关键字之后的任何内容(在本例中为" house")。有很多例子如何做到这一点,但我也想学习这个项目是一个很好的设计模式,这样的问题。我不想只在Server.java和Client.java这两个类中实现所有内容。

所以我开始使用Server类在端口上启动服务器并等待客户端。当他从客户端获得请求时,Server类将输入委托给类" RequestHandler"。这个类使用switch-case部分来检测像" Say"或"关闭"并通过接口调用相应的方法。

这是一个好模式吗?问题是例如服务" SHUTDOWN"。我必须随身携带Socket对象到执行命令的方法。或者这种模式不适合用更多功能升级服务器?请帮助改进!

由于

public class Server {
private int port;
private ServerSocket server;

public Server(int port) throws Exception{
    this.port = port;
    try{
          server = new ServerSocket(port);      
     }catch(Exception e){
          System.out.println("Server kann nicht gestartet werden: "+e.getMessage());
          throw e;
     }
}

public Server(int port){
    this.port = port;
}

public void start(){
    Socket client;
    Thread thread;

    while (true) {
        try {
            client = server.accept();
            // Verbindung eingegangen, Objekt erzeugen und in Thread laufen lassen
            System.out.println("Verbindung von "+client.getInetAddress());
            CommandHandler handler = new CommandHandlerImpl(client,new ControllerImpl());
            thread = new Thread(handler);
            thread.start();
        }
        catch (Exception e) {
          System.out.println("Verbindungsfehler: "+e);
        }
      }
}

}

public class CommandHandlerImpl implements CommandHandler{

private final String regex = " ";
private IController controller;
private Socket client;

public CommandHandlerImpl(Socket client, IController controller){
    this.client = client;
    this.controller = controller;
}

@Override
public String getCommand(String abstractString) throws Exception {
    String result;
    String[] arr = abstractString.split(regex);
    String command = arr[0];

    String s = "";
    if(arr.length > 1){
        s = arr[1];
    }
    switch (command) {
    case "CAPITALIZE":
        result = controller.capitalize(s);
        break;
    case "BYE":
        result = controller.sayBye();
        break;
    case "SHUTDOWN":
        result = controller.shutdown(s);
        break;
    default:
        result="Command nicht gefunden!!!";
    }
    return result;
}

@Override
public void run() {
    String line, res;
    try {
        PrintWriter out = new PrintWriter(client.getOutputStream());
        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));

        while (true) {
            line = in.readLine();
            System.out.println(line);
            res = null;
            if (line != null){
                res = getCommand(line);
            }
            if (res == null){
                break;
            }
            out.println(res);
            out.flush();
        }
          System.out.println("Verbindung von "+client.getInetAddress()+" beenden.");
          client.close();
    } catch (IOException e) {
        e.printStackTrace();
    }catch(Exception e){
        e.printStackTrace();
    }
}

}

IController是一个使用String执行某些操作的接口,并返回一个String,以便将其发送回客户端。 这是好事还是如何做好设计?

1 个答案:

答案 0 :(得分:3)

  

这个类使用switch-case部分来检测像“Say”这样的命令   或“SHUTDOWN”并通过接口调用相应的方法。

     

这是一个好模式吗?

一般情况下,不应使用开关案例,除非所有案例都是最终确定。如果我们知道有扩展名,就像你的情况一样,我们应该使用switch-cases。

根据您的需要,您可以使用CommandStrategy。如果您的操作组在逻辑上非常相似,请使用策略,否则使用命令

当我读到你的问题时,我认为命令更适合你。

我试图用Command模式实现概述解决方案,但是有些难以理解你的代码片段。一般来说,只要你的代码对于读取它的外人来说并不是很反映,你就应该使用注释。我想你可以理解我提到的来源。

此外,如果要将String从客户端映射到所需的Command对象,请使用Java Map。不要使用Switch-cases或if-else梯子,这肯定会让它变得混乱。请提出问题。 :))