I am designing a multiplayer online game for the sake of learning.
Several clients connect to a server that contains the true representation of the game world. Every client keeps track of a subset of that representation. I store the representations in a Context. The clients and the server change the state of the global context by passing various action classes around. One example is the MoveEntityAction, another is the TalkAction, and they all implement an interface called Action. In principle, the game is played by a flow of Action instances.
However, passing actions back and forth requires some fiddling. First, provide a definition of how they are read and written to the network. Second, protocol to translate them back and forth between the global and local contexts (different coordinate systems, etc). Third, let the server determine which actions need to preceed another action (I hope that is made clear by the pseudo-code below).
Right now, this process relies on several helper classes, each implementing an interface called Writer, Reader, ContextSwitcher and PrerequisiteFinder.
This has made me do the following:
Create a lookup table, ActionLibrary, that defines methods such as getReader(int actionId), getWriter(<Class <? extends Action> a), etc.
The classes that implement the helper interfaces are highly dependent on their associated Action class.
My game will have quite many classes implementing the Action interface, which means that every such class would require the implementation of 3 additional helper classes, each containing the protocol for dealing with a specific action. For example, MoveEntityReader, MoveEntityWriter, MoveEntityContextSwitcher, MoveEntityPrerequisiteFinder.
In spite of trying to adhere to the single responsibility principle, this approach does not feel very flexible. In fact, it feels quite awkward to distribute small pieces of protocol over several classes like this. And the ActionLibrary class does not feel like the best practice to associate these classes with each other.
Below is some example code of how an action might "flow" back and forth between the client and the server. Please note that this is pseudo-code written for this example, but hopefully it captures the essentials of what my real code does. In the below code, each Entity can be regarded as a client.
Human input (dragging and dropping an item on the screen) generates an instance of moveEntityAction. It is passed to the network stream as follows
writer = ActionLibrary.getWriter(moveEntityAction);
writer.writeTo(outputStream, moveEntityAction);
Server receives a packet with an ID and translates it to the global context, the servers representation of the game world:
reader = ActionLibrary.getReader(Id);
localAction = reader.readFrom(inputStream);
globalAction = ActionLibrary.getContextSwitcher(localAction.getClass(), playerContext, globalContext).apply(localAction);
After verifying that the action is OK, the server decides to broadcast the action to all the other clients. However, before it can do that it must broadcast the "prerequisites" of that action to every client. For example, if a MoveEntityAction moves an entity into the screen of a second entity, a PlaceEntityAction must be sent to the second entity first, so that it has an object to move. That happens as follows:
List<Entity> spectators = globalContext.getActionSpectators(globalAction);
for (Entity spectator : spectators) {
List<Action> prerequisiteActions = ActionLibrary.getPrerequisiteFinder(globalAction.getClass()).get(spectator, globalAction, globalContext);
spectatorContext = globalContext.getContextOf(spectator);
// Broadcast prerequisite actions (if any)
for (Action globalPreAction : prerequisiteActions) {
localPreAction = ActionLibrary.getContextSwitcher(globalPreAction.getClass(), globalContext, spectatorContext).apply(globalPreAction);
writer = ActionLibrary.getWriter(localPreAction);
writer.writeTo(outputStream);
}
// Finally, send the instigating action:
localAction = ActionLibrary.getContextSwitcher(globalAction.getClass(), globalContext, spectatorContext).apply(globalAction);
writer = ActionLibrary.getWriter(localAction);
writer.writeTo(outputStream);
}
// Execute the action on the globalContext
globalContext = globalAction.execute(globalAction);
then, the client receives each packet and its id, finds the corresponding reader and applies that to its local Context:
reader = ActionLibrary.getReader(Id);
localAction = reader.readFrom(inputStream);
context = localAction.execute(context);
I am basically looking for some thoughts and advice on the matter. How would you clean this mess up? Maybe there is a design pattern for situations like mine where I risk entangling myself with a bunch of helper classes.
Thank you in advance!
Edit: I would like to avoid Serializable for several reasons. One being that the client might not be written in Java. Another being that I want to pick up a general best practice here because in time I might turn this into a private server for another game that I do not own the network protocol for.
Within Java you can create an Observer-Observable set of classes in which the Observable can call the Observer. You can also in java explicitly reference an owning class instance in a child instance of another class and call the owning class instance's public functions.
Which is the better approach to take? Which is more beneficial in different scenarios, one example being Multi-Threading?
The Observer Pattern should be used whenever you don't know or don't care who is observing you. This is the key-concept in event-driven programming. You don't have any control of who is observing or what they do when you broadcast your events. Like you already mentioned in your comments, this is great for decoupling classes.
An example of a usage could be in a plugin-architecture:
You write a basic mail-server that broadcasts whenever a mail is received. You could then have a spam-plugin that validates the incoming mail, an auto-reply service that sends a reply, a forward service that redirects the mail and so on. Your plain mail server (the observable) doesn't know anything about spam, replies or forwarding. It just shouts out "Hey, a new mail is here" not knowing if anyone is listening. Then each of the plugins (the observers) does their own special thing, not knowing anything about each other. This system is very flexible and could easily be extended.
But the flexibility provided by the Observer Pattern is a two-edged sword. In the mail-server example, each plugin handles the incoming mail in total isolation from each other. This makes it impossible to setup rules like "don't reply or forward spam" because the observers doesn't know about each other - and even if they did, they wouldn't know in what order they are executed or has completed. So for the basic mail-server to solve this problem, It'll need to have references to the instances that does the spam/reply/forward actions.
So the Observer Pattern provides flexibility. You could easily add a new anti-virus plugin later, without having to modify your plain mail server code. The cost of this flexibility is loss of control of the flow of actions.
The reference approach gives you total control of the flow of actions. However you would need to modify your plain mail server code if you ever need to add support for an anti-virus plugin.
I hope this example gives you some ideas of the pros and cons of each approach.
In regards to multi-threading, one approach isn't favorable over the other.
Closed. This question is opinion-based. It is not currently accepting answers.
Closed 4 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I am studying the command design pattern, and I am quite confused with the way of using it. The example that I have is related to a remote control class that is used to turn lights on and off.
Why should I not use the switchOn() / switchOff() methods of Light class rather than having separate classes and methods that eventually call switchOn / switchOff methods?
I know my example is quite simple, but that is the point. I could not find any complex problem anywhere on the Internet to see the exact usage of the command design pattern.
If you are aware of any complex real world problem that you solved that can be solved using this design pattern please share that with me. It helps me and future readers of this post to better understand the usage of this design pattern. Thanks
//Command
public interface Command {
public void execute();
}
//Concrete Command
public class LightOnCommand implements Command {
//Reference to the light
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.switchOn(); //Explicit call of selected class's method
}
}
//Concrete Command
public class LightOffCommand implements Command {
//Reference to the light
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.switchOff();
}
}
//Receiver
public class Light {
private boolean on;
public void switchOn() {
on = true;
}
public void switchOff() {
on = false;
}
}
//Invoker
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
//Client
public class Client {
public static void main(String[] args) {
RemoteControl control = new RemoteControl();
Light light = new Light();
Command lightsOn = new LightsOnCommand(light);
Command lightsOff = new LightsOffCommand(light);
//Switch on
control.setCommand(lightsOn);
control.pressButton();
//Switch off
control.setCommand(lightsOff);
control.pressButton();
}
}
Why should not I easily use code like the following?
Light light = new Light();
switch(light.command) {
case 1:
light.switchOn();
break;
case 2:
light.switchOff();
break;
}
The main motivation for using the Command pattern is that the executor of the command does not need to know anything at all about what the command is, what context information it needs on or what it does. All of that is encapsulated in the command.
This allows you to do things such as have a list of commands that are executed in order, that are dependent on other items, that are assigned to some triggering event etc.
In your example, you could have other classes (e.g. Air Conditioner) that have their own commands (e.g. Turn Thermostat Up, Turn Thermostat Down). Any of these commands could be assigned to a button or triggered when some condition is met without requiring any knowledge of the command.
So, in summary, the pattern encapsulates everything required to take an action and allows the execution of the action to occur completely independently of any of that context. If that is not a requirement for you then the pattern is probably not helpful for your problem space.
Here's a simple use case:
interface Command {
void execute();
}
class Light {
public Command turnOn();
public Command turnOff();
}
class AirConditioner {
public Command setThermostat(Temperature temperature);
}
class Button {
public Button(String text, Command onPush);
}
class Scheduler {
public void addScheduledCommand(Time timeToExecute, Command command);
}
Then you can do things such as:
new Button("Turn on light", light.turnOn());
scheduler.addScheduledCommand(new Time("15:12:07"), airCon.setThermostat(27));
scheduler.addScheduledCommand(new Time("15:13:02"), light.turnOff());
As you can see the Button and Scheduler don't need to know anything at all about the commands. Scheduler is an example of a class that might hold a collection of commands.
Note also that in Java 8 functional interfaces and method references have made this type of code even neater:
#FunctionalInterface
interface Command {
void execute();
}
public Light {
public void turnOn();
}
new Button("Turn On Light", light::turnOn);
Now the methods that are turned into commands don't even need to know about commands - as long as they have the correct signature you can quietly create a anonymous command object by referencing the method.
Let us focus on the non-implementation aspect of the command design, and some main reasons for using the Command desing pattern grouped in two major categories:
Hiding actual implementation of how the command is executed
Allow methods to be built around command, aka command extensions
Hide implementation
In most programming, you'll want to hide away implementation so that when looking at the top-most problem, it consists of a comprehensible subset of commands/code. I.e. You don't need/want to know the gory details of how a light is switched on, or a car is started. If your focus is to get the car started, you don't need to understand how the engine works, and how it needs fuel to enter the engine, how the valves work, ...
Indicating the action, not how it is done
A command gives you this kind of view. You'll immediately understand what the TurnLightOn command does, or StartCar. Using a command you'll hide the details of how something is done, whilst clearly indicating the action which is to be executed.
Allow changing of inner details
In addition, lets say you later on rebuild your entire Light class, or a Car class, which requires you instantiate several different objects, and possibly you need to something else before actually doing your wanted operation. In this case if you had implemented the direct access method, in a lot of places, you would need to change it in all places where you've coded it beforehand. Using a command, you can change the inner details of how to do stuff without changing the calling of the command.
Possible command extensions
Using a Command interface gives you an extra layer between the code using the command, and the code doing the actual action of the command. This can allow for multiple good scenarios.
Security extension, or interface exposure
Using a command interface, you can also limit access to your objects, allowing you to define another level of security. It could make sense to have a module/library with a fairly open access so that you could handle internal special cases easily.
From the outside, however, you might want to restrict the access to the light so that it is only to be turned on or off. Using commands gives you the ability to limit the interface towards a class.
In addition if you want, you could build a dedicated user access system around the commands. This would leave all of your business logic open and accessible and free of restrictions, but still you could easily restrict access at the command level to enforce proper access.
Common interface to executing stuff
When building a sufficient large system, commands gives a neat way to bridge between different modules/libraries. Instead of you needing to examine every implementation detail of any given class, you can look into which commands are accessing the class.
And since you are leaving out implementation details to the command itself, you could use a common method to instantiate the command, execute it and review the result. This allows for easier coding, instead of needing to read up on how to instantiate that particular Light or Car class, and determining the result of it.
Sequencing of commands
Using commands, you can also do stuff like sequencing of commands. That is since you don't really matter if you are executing the TurnOnLight or StartCar command, you can execute sequences of theses as they are executed the same way. Which in turns can allow for chains of commands to be executed, which could be useful in multiple situation.
You could build macros, execute sets of commands which you believe are grouped together. I.e. the command sequence: UnlockDoor, EnterHouse, TurnOnLight. A natural sequence of commands, but not likely to made into a method as it uses different objects and actions.
Serialisation of commands
Commands being rather small in nature, also allows for serialisation quite nicely. This is useful in server-client context, or program-microservice context.
The server (or program) could trigger a command, which then serialises the command, sends it over some communication protocol (i.e. event queue, message queue, http, ... ) to someone actually handling the command. No need to first instantiate the object at the server, i.e. a Light which could be light-weight (pun intended), or a Car which could be a really large structure. You just need the command, and possibly a few parameters.
This could be a good place to introduce to the CQRS - Command Query Responsibility Separation pattern for further studies.
Tracking of commands
Using the extra layer of commands in your system could also allow for logging or tracking commands, if that is a business need. Instead of doing this all over the place, you can gather tracking/logging within the command module.
This allows for easy changes of logging system, or addition of stuff like timeing, or enabling/disabling logging. And it's all easily maintained within the command module.
Tracking of commands also allows for allowing undo actions, as you can choose to re-iterate the commands from a given state. Needs a little bit of extra setup, but rather easily doable.
In short, commands can be really useful as they allow connection between different parts of your soon-to-be-large program, as they are light-weight easily remembered/documented and hides the implementation details when so needed. In addition the commands allows for several useful extensions, which when building a larger system will come in handy: i.e. common interface, sequencing, serialisation, tracking, logging, security.
The possibilities are many, but it'd typically be something like:
building a command-line framework that abstracts out the parsing of options from the action. Then you can register an action with something like opts.register("--on", new LightOnCommand()).
letting users drag and drop a sequence of actions to execute as a macro
registering a callback when some event is triggered, like on(Event.ENTER_ROOM, new LightOnCommand())
The general pattern here is that you've got one piece of the code responsible for figuring out that some action needs to be taken without knowing what that action is, and another piece of the code knows how to do an action but not when to do it.
For instance, in that first example, the opts instance knows that when it sees a command line option --on, it should turn the lights on. But it knows this without actually knowing what "turn the lights on" means. In fact, it could well be that the opts instance came from a third-party library, so it can't know about lights. All it knows about is how to accociate actions (commands) with command-line options that it parses.
You don't have to. Design patterns are simply guidelines that some people in the past have found useful when writing applications of significant complexity.
In your case, if what you have to do is turn the light switch on and off, and not much else, the second option is a no brainer.
Less code is almost always better than more code.
The example ICommand you give is rather limited and is only of real use in a programming language that does not have lambda expressions. Sprinter covers this well in his answers showing the use of command factories.
Most cases of the command pattern include other methods for example, CanRun and/or Undo. These allows a button to update its enable state based on the state of the command, or a application to implement an undo stack.
Like most design patterns, the Command Pattern comes into its own where things get a little more complex. It is also well know, so helps make your code clearly to most programmers.
You can do whatever you think but it is good to follow the pattern for usability of manageability of code.
In real life example, Light would be an interface. You have different implementations of Light like LEDLight, TubeLight
If you execute the concrete command through Inovker ( RemoteControl), you need not worry about changes in method name in Receiver. switchOn() in Light can be changed to switchOnDevice() in future. But it does not effect Invoker since ConcreteCommand (LightsOnCommand) will make relevant changes.
Assume the scenario, where you publish your interfaces to one service (Service A) and implementation in other services (Service B).
Now Service A should not know about changes in Receiver.
Invoker provides loose coupling between Sender & Receiver of the message.
Have a look at some more related SE questions:
Using Command Design pattern
Command Pattern seems needlessly complex (what am I failing to understand?)
There're couple of benefits of Command pattern that I've experienced. But first of all, I would like to remind that as all other patterns this pattern is also to increase code readability and bring some common understanding to your (probably) shared code base.
I use this pattern to transition from a method-oriented interface to a command-oriented interface. That means, I'm encapsulating method calls into concrete commands along with necessary data. It makes the code more readable yes but more importantly I can treat methods as objects which lets you easily add/remove/modify commands without increasing the complexity of the code. So it makes it easy to manage as well easy to read.
Secondly, since you've your methods as objects, you can store/queue them to execute them later. Or to cancel them even after you've executed them. This is where this pattern helps you to implement "Undo".
Finally, command pattern also used to decouple command execution and commands themselves. It's like a waiter doesn't know about how to cook the orders that he received. He doesn't care. He doesn't have to know. If he'd know that, he'd be working as a cook as well. And if the restaurant owner wants to fire the waiter, he/she ends up with having no cook as well. Of course this definition is not special or related to command pattern only. That's explains why we need decoupling or dependency management in general.
Design patterns are basically developed to solve complex problem or in other words we can say that they are used to prevent your solution to become complex. They provide us the flexibility to add new functionalities in future without making much changes in our existing code. Open for extension, closed for modification.
Command Pattern basically encapsulates a request as an object and thereby letting you parameterize other objects with different requests and support undoable operations.
When we see a remote control that is a best example of command pattern. In this case we have associated a concrete command to each button and that command has an information of the receiver to act upon.
In your example of switch case, suppose if you want to associate a button on remote control to fan instead of light then again you will have to change the existing code because you need to associate a button with a command. This is the essence of command pattern where it provides you a flexibility to associate any command with a button so that at run time you can change the functionality. Although in general TV remote you don't have this feasibility i.e. you can't make volume up button to work as volume down. But if you use any application to control your TV then you can assign any button any of the available command.
Further, using command pattern you can have a set of commands for a particular functionality to achieve, i.e. macro command. Hence if you think at a broader level then this pattern can get you the flexibility to extend functionalities.
Command pattern help us in decoupling invoker(remote control) and Receiver (Light,Fan,etc) with the help of command object(LightOnCommand, FanOffCommand, etc).
I have a general question about a best practice or pattern to solve a problem.
Consider that you have three programs running on seperate JVMs: Server, Client1 and Client2.
All three processes make changes to an object. When the object is changed in either client, the change in the object (not the new object) must be sent to the server. It is not possible just to send the new object from the client to the server because both clients might update the object at the same time, so we need the delta, and not the result.
I'm not so worried about reflecting changes on the server back to the clients at this point, but lets consider that a bonus question.
What would be the best practice for implementing this with X amount of processes and Y amount of object classes that may be changed?
The best way i can think of is consistently using the Command pattern to change the object on the client and the server at the same time, but there has to be a better way?
One of the possible ways to solve that is the Remote Method Invocation system in Java. Keep all the data values on the Server, then have the clients use remote calls to query them.
This would however require some smart caching to reduce the amount of pointless calls. In the end you would end up with something similar to the Command Pattern.
Modern games try to solve this issue with something I'd call an Execute-Then-Verify pattern, where every client has a local copy of the game world, that allows him to come to the same conclusion for each action as the server would. So actions of the player are applied to the local copy of the game world assuming that they are correct, then they are sent to the server, which is the ultimate instance to either accept that or revoke it later on.
The benefit of this variant of local caching is, that most players do not experience much lag, however in the case of contradictory actions they might experience the well-known roll-backs.
In the end it very much depends on what you are trying to do and what is more important for you: control over actions or client action flow.
Hey guys,
I'm using GWT to code a simple multiplayer board game.
And while I was coding the question came up to my mind:
At first I though my client could simply communicate with the server via RemoteServices calls, so if a client wanted to connect to a game he could do as follows:
joinGame (String playerName, String gameName)
And the server implementation would do the necessary processing with the argument's data.
In other words, I would have lots of RemoteService methods, one for each type of message in the worst case.
I thought of another way, which would be creating a Message class and sub-classing it as needed.
This way, a single remoteService method would be enough:
sendMessage (Message m)
The messages building and interpreting processing too would be done by specialized classes.
Specially the building class could even be put in the gwt-app shared package.
That said,
I can't see the benefits of one or another. Thus I'm not sure if I should do one way or another or even another completely different way.
One vs other, who do you think it is better (has more benefits in the given situation)?
EDIT: A thing I forgot to mention is that one of the factors that made me think of the second (sendMessage) option was that in my application there is a CometServlet that queries game instances to see if there is not sent messages to the client in its own message queue (each client has a message queue).
I prefer the command pattern in this case (something like your sendMessage() concept).
If you have one remote service method that accepts a Command, caching becomes very simple. Batching is also easier to implement in this case. You can also add undo functionality, if that's something you think you may need.
The gwt-dispatch project is a great framework that brings this pattern to GWT.
Messaging takes more programmer time and creates a more obfuscated interface. Using remote service methods is cleaner and faster. If you think there are too many then you can split your service into multiple services. You could have a service for high scores, a service for player records, and a service for the actual game.
The only advantage I can see with messaging is that it could be slightly more portable if you were to move away from a Java RPC environment but that would be a fairly drastic shift.