2016-10-10 12 views
3

私はプログラミングが新しく、クライアントが「SAYハウス」のようなコマンドを送信し、サーバがコマンドとして「SAY」というキーワードを検出し、後にあるものを返す単純なクライアントサーバシステムをコーディングしたいキーワード(この場合は「家」)。これを行うには多くの例がありますが、私もこのプロジェクトで学びたいことは、このような問題の良い設計パターンです。私は、Server.javaやClient.javaのような2つのクラスだけですべてを実装したくない。クライアント/サーバのデザインパターン

私はポートでサーバーを起動してクライアントを待つServerクラスを使い始めました。クライアントからRequestを受け取ると、Serverクラスは入力を "RequestHandler"クラスに委譲します。このクラスは、 "Say"や "SHUTDOWN"のようなコマンドを検出するswitch-case部分を行い、対応するメソッドをインターフェイス上で呼び出します。

これは良いパターンですか?問題は、たとえば、サービス「シャットダウン」です。コマンドを実行するメソッドに、私と一緒にソケットオブジェクトを持っていく必要があります。または、このパターンは、より多くの機能を持つサーバーをアップグレードするために良いのではないでしょうか?改善のために助けてください!

おかげ


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で何かをやっインタフェースであり、私がクライアントに戻ってそれを送ることができるように文字列を返します。 。 これは良いですか、それとも良いデザインになるべきでしょうか?

+0

「サーバー」のコードを表示すると便利です。あなたがあなたがそれをやっているかについての一般的な考えを得るために書いたと言った、「java」です。また、あなたがしようとしていることを達成するための多くのアプローチがあるため、あなたの質問はかなり広範なものです。 – px06

答えて

3

このクラスでは、 "Say"と答えてください。 または "SHUTDOWN"のようなコマンドを検出し、対応するメソッドをインターフェイス経由で呼び出します。

これは良いパターンですか?

すべてのケースが完了していない限り、スイッチケースは一般的にファイナライズです。あなたの場合のように、延長があることが分かっている場合は、ではなく、でスイッチケースを使用する必要があります。

あなたの場合、必要に応じてCommandまたはStrategyのいずれかを使用できます。あなたの操作のセットが論理的に似ている場合は、の戦略、それ以外の場合はコマンドに行ってください。

私はあなたが質問を読んだので、私はコマンドがより適していると思う。

私は、コマンドパターンの実装で解決策を説明しようとしましたが、コードの一部を理解するのはやや難解でした。一般的には、あなたのコードがそれを読む外部者をあまり反映していないときはいつでも、コメントを使うべきです。私が言及した情報源を理解することができると思います。

さらに、文字列をクライアントから目的のCommandオブジェクトにマップする場合は、Javaマップを使用します。スイッチケースやそれ以外の場合は間違いなく厄介なラダーを使用しないでください。もし質問があれば提起してください。 :))

+0

ありがとう、私は後でコマンドパターンを使用しようとします。しかし、私はswtichのケースが必要です。サーバーはクライアントから文字列を取得するので、どのコマンドを使用するかを区別しなければなりません。または、クライアントソケットからの着信ストリームを分析し、正しいコマンドで応答する別の方法がありますか? – mrprinze

+0

マップを使用してスイッチケースをスキップできます。 Map マップ。これで、クライアントから取得しているStringを使用して、目的のコマンドオブジェクトを作成できます。 map.get( "someString"):))あなたが理解したいと思っています。 –

+0

ありがとうございました。 OK今私は次のデザインは大丈夫ですか?: サーバを起動するためのSocketを持つクラス**サーバ**とクライアントの接続を待ちます。クライアントが接続した後、彼は上記の私のコードのような新しいスレッドを作成します(** CommandHandler **)。そして、** CommandHandler **が呼び出し側です。それから私は**コマンド**インターフェイスと**具体的な**コマンドクラスを持っています。具体的なクラスでは、実際の**実際の**送信メッセージをクライアントに返すクラスを呼び出します。これは正しいですか?パターンを使用しているので、私は誰が私のケースで誰であるのかわかりません。 – mrprinze

関連する問題