Java防止方法重复用于不同目的

时间:2014-01-27 21:39:10

标签: java oop design-patterns

嘿,我有这两种方法:

private void sendMessage(String message) {
    ArrayList<Client> waiters = this.getPlayers().getWaitingRoom();
    for (Client c : waiters) {
        c.sendMessage(message);
    }
}   

第二种方法:

private void sendMessage(String message) {
    ArrayList<Client> players = this.getPlayers().getGame();
    for (Client c : players) {
        c.sendMessage(message);
    }
}

这些方法非常有用,因为我需要以某种方式向等候室中的客户端和游戏中的客户端发送消息,游戏中的客户端不应该听到我发送给客户的消息。候诊室,对面也是如此。

我提出了这个解决方案,使其成为一种方法,但我觉得这是一个非常糟糕的解决方案:

private void sendMessage(String message, int type) {
    ArrayList<Client> clients = (type == 0) ? this.getPlayers().getWaitingRoom() :
        this.getPlayers().getGame();
    for (Client c :clients) {
        c.sendMessage(message);
    }
}

这有效,但我想知道是否有适当的解决方案,更面向对象。但由于它使用相同的类型(ArrayList),我有点困惑&amp;丢失。

对此方法有更好设计的想法吗?

3 个答案:

答案 0 :(得分:4)

第一个明显的概括是声明

private void sendMessage(String message, Iterable<? extends Client> clients) {
    for (Client c : clients) {
        c.sendMessage(message);
    }
}   

允许调用

sendMessage("Message", this.getPlayers().getWaitingRoom());
sendMessage("Message", this.getPlayers().getGame());

顺便说一句:虽然ArrayList的明确声明通常没有必要。他们可以返回List<Client> ....

编辑:回答“为什么Iterable ......”这个问题:

Iterable是“最小”的接口,足以满足您在此方法中要执行的任务。您只想迭代所有元素。您不需要ArrayList。您不需要列表。你甚至不需要收藏品。你只需要一些可以改变的东西。

优点是可以使用许多不同的参数调用此方法:

Set<Client> set = ...
List<Client> list = ...
Queue<Client> queue = ...
sendMessage("Message", set); // Works
sendMessage("Message", list); // Works
sendMessage("Message", queue ); // Works

Set<SomeClassExtendingClient> setWithSpecialClients = ...
sendMessage("Message", setWithSpecialClients); // Works as well...

如果您宣布方法接收ArrayList<Client>,则无法传递LinkedList<Client>ArrayList<SpecialClient>。使用Iterable<? extends Client>,您可以获得最大的灵活性。

答案 1 :(得分:1)

您正在为该方法定义错误的输入。该方法的任务是将消息发送到客户端列表。它既不应关心也不了解这些客户的深层含义。所以它应该是这样的:

private void sendMessageToClients(String message, ArrayList<Client> clients) {
    for (Client c :clients) {
        c.sendMessage(message);
    }
}

确定您是选择候诊室还是游戏玩家的任务由该方法的来电者完成。

答案 2 :(得分:0)

Java枚举是以面向对象的方式设计的。使用枚举将使您的代码类型安全。

public enum Room {
    GAME, LOBBY;
}

private void sendMessage(String message, Room room) {
    ArrayList<Client> clients = (room == Room.LOBBY) ? this.getPlayers().getWaitingRoom() :
        this.getPlayers().getGame();
    for (Client c :clients) {
        c.sendMessage(message);
    }
}

注意:如果您有两种以上的可能性,则可以使用switch语句。

编辑:其他答案将是首选解决方案;这只是另一种选择。