Related
I am trying to create a game involving machines and items. I have a simple item interface and every item will implement this.
I would usually just create a class for every item, but there could potentially be thousands of items, and it doesn't feel right to create thousands of files for all the items. This applies to other large amounts of types of objects I might have. (ground tiles, entities)
I need a type safe way to store all these implemented interfaces. I need to easily be able to create a new item in my code, with only the name of the item.
I was thinking of having a huge class with subclasses holding lots of final constants that would all be anonymous classes, but this also seems like a bad way of doing this.
Is there any good way to do what I have in mind? (Sorry that this is a little vague)
My item interface is currently,
package com.bobona.craftable.model;
import com.bobona.craftable.CraftableGame;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
public interface Item {
String getId();
Map<String, Integer> getValues();
void onUse(AtomicReference<CraftableGame> game, Long entityUsedByIndex);
void onSecondaryUse(AtomicReference<CraftableGame> game, Long
entityUsedByIndex);
}
You're going to need to think about the hierarchy of your game first before you start coding anything.
You haven't described anything about this game, like what's in it or what the objects are or what things can interface with what, so I'll describe a popular game I like - Factorio.
In this game, amongst other things, there are a few things to describe:
Items which allow you to craft other items
Belts which move items
Assemblers which turn items into other items
So I would start with describing the basic hierarchy of how these things interact.
A class for items, and an enum to allow us to describe what the item is and how we can interact with it (if it's craftable or not, which are rules owned by the assemblers)
A class for belts, with as many belt types as we want to support (right now the game has 3)
A class for assemblers, which describe how many items can be accepted at once as well as how fast they craft things
You'll have to understand how your items interact with the environment before you describe rules. For example:
Items can be placed on belts through the use of an inserter.
Items can be placed into an assembler through the use of an inserter.
This will require more thought on your part. But, the number of classes you should have would be small provided that there are only a handful of elements in the world.
This is a difficult design problem, and there is no one size fits all answer as far as I know. As mentioned by Makoto in another answer, much of your approach will be dictated by the actual details of your specific game.
I would usually just create a class for every item, but there could potentially be thousands of items, and it doesn't feel right to create thousands of files for all the items.
I completely agree with this statement.
I need a type safe way to store all these implemented interfaces.
I'm not sure that this is possible (literally as written), if we accept the previous statement that separate classes or interfaces aren't the correct approach. However, if instead of type safe you'll settle for verifiable at runtime by some yet-unspecified mechanism, then I think it's quite doable.
[From Comment] It also wouldn't be nice to use non type-safe values to define items in recipes, as that would quickly become a pain to debug and refactor.
I agree you'll want some sort of verification, but as previously mentioned full-blown compile-time type safety might not be feasible while also avoiding thousands of separate classes. I think the key here is to reliably detect errors, respond to them in a way that doesn't break the game, and generate sensible debug messages for the developer.
There are a lot of ways to go about accomplishing this; which one you choose is going to depend on your exact requirements, your preferences, and a number of implementation details that I have no way of knowing. Some things that I think you should look into or consider:
Inheritance probably won't work at all, for the reasons you've already identified.
Composition or the flyweight pattern might improve things initially, but probably won't scale the way you want.
You could go for a RDBMS approach, as outlined here.
You might try a JSON based approach or equivalent, as outlined here.
The component pattern fits my understanding of your problem very well.
This is an incredibly well written answer detailing how to implement the component pattern for entities (which I think include the types of items you were describing) using bit fields.
This is a very similar question to yours on the gamedev stackexchange with some good answers.
Personally I like the component pattern, and am a fan of using JSON or an equivalent language for specifying the items themselves. Hopefully at least some of the above information will help you as you iteratively modify your architecture to meet your gameplay requirements.
would usually just create a class for every item, but there could potentially be thousands of items, and it doesn't feel right to create thousands of files for all the items.
Yes, you should not be doing that. Classes act as blueprint of your object. We don't create a new class for every new object. If you see that all your items share a common attribute (e.g. name), then those can be used as the attribute of your base class:
public abstract class Entity{
protected String name;
public Entity(String name){
this.name = name;
}
}
Then for those object which is an Item, you can extends it to base class:
//example
public abstract class Monster extends Entity{
protected int damage;
//constructor not shown
}
If you also need to indicate whether an Entity is Ground or Air. You can also use Interface as such:
public Interface OnAir{
}
public Interface OnGround{
}
Then you can have:
//example
public class FlyingMonster extends Monster implements OnAir {
//your other attributes here
}
public class LandMonster extends Monster implements OnGround {
//your other attributes here
}
Now you have the flexibility to manipulate the type of object you want.
To store all your monsters (ground and air):
ArrayList<Monster> monsters = new ArrayList<>();
To store all entities including monsters:
ArrayList<Entity> entities= new ArrayList<>();
The above solution is to reply your question. However, I should mention that in game making, I wouldn't want to create that many classes. But instead I would store all my entities in a datafile. If there are special attributes for your entity. For example, a fire-based weapon which does 30% extra damage to all ice-based creture. I would not code this in Java as well. But instead store it in a script file. That fire-based weapon will then be referenced to the script file.
The same logic applies to your Non-Playable Characters.
So what is the benefit of storing them in scripts and datafiles? You can add / remove / edit your entities without the need to recompile your codes. You can change how the weapons work, how your character behaves, how your NPCs talk without changing anything in Java.
This means that you can now add new items into the game by just typing into the textfile.
I'm quite new to OOP/Design Patterns and I'm dealing with a design issue when it comes to separating the logical informations of my objects from their graphical status :
In the Java the musical application I'm trying to make I have a Chord class which is composed of either Note classes or Rest classes.
In these classes I store "logical" informations such as the midi value of a note, its velocity, etc.
I want to draw these chords on a Staff object (that extends some kind of GUI Panel object) : to do such thing I need to add some informations to my classes, such as the position of my objects on the staff or their symbol.
So, I made graphical "equivalent" of my classes, holding these graphical informations, as well as encapsulating my logical Chords, as you can see in the following diagram :
http://i.imgur.com/b7p00uy.png
But I'm stuck with something that I think is really strange : my diagram is mirrored in its center (which make me think my graphical classes are somewhat useless) and I can't really create a GraphicChord object from a Chord on the fly because I can't know if I should make a GraphicNote or a GraphicRest for each SimpleElement my Chord contains...
I'm sure there's something about design principles I must be doing very wrong but I can't find another way to add graphical informations to my objects…
Can you please help me ?
You are working with 2 different groups of related objects. You are doing it right in your diagram, having the basic idea, but, needs some "cleanup".
As you already notest, one group is composed by the objects that store the data or model. A song object may be composed, by several notes.
The other group, represents the visual or graphical representation of the data or model. You may display a music pentagram, that has several sections, and the notes of the same song & rests, are displayed visually.
You may use the "Decorator Software Design Pattern":
http://en.wikipedia.org/wiki/Decorator_pattern
But I'm stuck with something that I think is really strange :
my diagram is mirrored in its center
(which make me think my graphical classes are somewhat useless)
and I can't really create a GraphicChord object from a Chord
on the fly because I can't know if I should make a
GraphicNote or a GraphicRest for each SimpleElement my Chord contains...
In this case of problem, it's OK, that many classes are duplicated or "mirrored", since a group represent the model, and, another group, the visual representation of the same model.
Do not get surprised, if other people say you are wrong, because you have a duplicate of the classes. In this special case of scenario, the duplication of information, is right.
Now, about your question, think like a non programming user. A non programming user, doesn't think about the data or model classes. He / She, thinks about the Interface / GUI classes, and, works with them.
When the user (or you) create a chord, then, he / she really creates a GraphicalChord, and, the GraphicalChord, will create an internal Chord, behind the scenes. The user adds a Note or Rest, and, really adds, a Graphical Note, or, a Graphical Rest, and, those objects, will create a Data Note, or Data Rest, and, added to the Chord.
I suggest to add a prefix or suffix to you non graphical classes, like "RealChord", "DataChord", or alike, in order to avoid confusion with the GUI Classes.
In the case of "SimpleElement" since, it's already known that it will have 2 subclasses, you may add a enumerated property to know which class, it is.
public enum ElementTypeEnum {
UNASSIGNED,
NOTE,
REST
}
public class SimpleElementClass {
private ElementTypeEnum _ElementType;
public void setElementType(ElementTypeEnum n){
_ElementType = n;
}
public ElementTypeEnum getElementType(){
return _ElementType;
}
/* other members */
} // class SimpleElementClass
public class NoteClass extends SimpleElementClass {
/* other members */
} // class NoteClass
public class RestClass extends SimpleElementClass {
/* other members */
} // class RestClass
This way, when you add any object that implement the subclasses, you can quickly infer, which type is it. The Chord classes, works at some level with the "SimpleElementClass" class, instead of the subclasses.
Cheers
I can't really create a GraphicChord object from a Chord on the fly because I can't know if I should make a GraphicNote or a GraphicRest for each SimpleElement my Chord contains
If that is the only reason for having the Graphic objects you can use instanceof to check what kind of SimpleElement you have.
if(myCurrentSimpleObject instanceof Note)
{
// create Graphic object on the fly
}
If you want to avoid using instanceof you could change your SimpleElement class by adding an abstract method to determine the object type.
abstract boolean isNote();
The child classes would have to implement this method and return a fixed true or false.
This can be scaled to multiple classes by returning an enumeration value that describes the class.
If your child classes have methods specific to them, you will still have to cast them to the correct class. And if you want to avoid 'unchecked class cast' compiler warnings while doing this you are still stuck with instanceof
So I'm working on creating a visualization for a data structure in Java. I already have the implementation of the data structure (Binary Search Tree) to start with, but I need to add some additional functionality to the included node class. As far as conventions and best practices are concerned, should I create a subclass of the node with this added functionality or should I just modify what I have and document it there?
My question is similar to what's asked here but that's a little over my head.
I know it probably doesn't matter much for what I'm doing, so I'm asking this more as a general thing.
Edit: I probably should have been more clear. My modifications don't actually change the original implementation other than to add a couple of extra fields (x and y coords plus a boolean to set whether that node is highlighted) and functions to access/modify those fields. Also the node class I'm working with is included in the BST implementation
From reading your answers it seems like there's arguments to be made for either case. I agree that creating a separate class or interface is probably the best thing to do in general. Creating another class seems like it could get tricky since you'd still need a way to extract the data out of the node. The BST implementation I'm using is generic and doesn't have any such functionality by itself in the Node class or the BST class to just return the data so at minimum I have to add that.
Thanks for the informative replies.
The question to answer is, is the 'base functionality' useful, even disirable, when you're not visualizing the data structure?
You might not even want to extend the class at all. Without more detail, it seems to me that you have a datastructure that works. You could create a NEW class that knows how to vizualise it.
That is, instead of a datastructure than knows how to visualize itself, you have a datastructure, and another class that knows how to visualize the datastructure. Heck - you may find that that evolves into another whole class hierarchy because you might need to visualize queues, stacks, etc. etc. NOTHING to do wiht your binary search tree.
Since you're asking in general, here's the short answer: it really depends on the situation.
First off, subclasses are assumed to have an "IS-A" relationship with their parent classes. If you can't say that your new subclass IS A specific kind of the original class, you're asking the wrong question, and should be making a new, unrelated class.
If the new code is closely related to the core purpose of the class, and applies to all members of the class (e.g. all BSTs), it may be better to modify. High cohesion is good.
If your new code is related to the core purpose of the class but has to do with only some objects of that type (e.g. only BSTs that are balanced), subclassing is probably the way to go.
Depending on what you're changing, how many places your code is used, how many different people/organizations are using it, &c., your changes might lead to unexpected behavior in other code, so you should think twice before modifying existing code. That doesn't mean automatically subclassing commonly used things; that would often be wrong for the reasons described above.
In your specific case, I agree with n8wrl; since visualization has nothing to do with data structures, it's probably better to implement a whole separate Visualizable interface than make a DrawableBSTNode subclass.
I would say that in the general case of adding functionality to an existing implementation, you should extend the existing implementation rather than modify it.
And here's my reasoning. If that node is used anywhere aside from the Binary Search Tree implementation, then when you modify it you'll need to find everywhere it is used to ensure that none of those places conflict with your modifications. While just adding functionality in the form of new methods generally won't cause problems, it could cause problems. You never know how an object is used.
Second, even if it is only used in the Binary Search Tree, you'll still need to make sure that the BST's implementation will play nice with your modifications.
Finally, if you do extend it, you don't have to worry about points one and two. And you get the added bonus of having your modifications kept separate from the original implementation for all time. This will make it easier to track what you have done and comment on it.
There's no simple answer, knowing when and how to add functionality is a something you have to learn over time.
Just adding to the base class seems like the easy solution, but it's polluting your base class. If this is a class you could reasonably expect another program (or even part of your program) to use does the functionality you are adding make sense in the context of your class's responsibility? If it doesn't this is probably a bad move. Are you adding dependencies linking your base class to your specific use? Because if you are that's throwing code reuse right out the window.
Inheriting is the solution a lot of engineers gravitate to, and it's a seductive route. But as I've grown as an engineer it's one that I use sparingly. Inheritance should only be used in true is-a relationships, and you need to respect behavioral subtyping
or you are going to regret it later on. And since Java only allows single inheritance it means you only get one shot at subtyping.
Composition (especially with interfaces) is often a better idea. Often what looks like a is-a relationship is really a has-a one. Or sometimes all you really need is a helper class, that has many functions that take your original class as an argument.
However with composition there is one issue, want to store these objects in your tree. The solution here is interfaces. You don't want a tree that stores Nodes. You want to objects that have an interface that can give you a node.
public interface HasNode {
public Node getNode();
}
Your node class is a HasNode with getNode just returning this. Your NodeVisualizer class is also a HasNode, and now you can store NodeVisualizers in your tree as well. Of course now you have another problem, your tree could contain NodeVisualizers and Nodes, and that wouldn't be good. Plus when you get a HasNode back from the tree functions you have to cast them to the right instance and that's ugly. You'll want to use templates for that, but that's another answer.
Mixing up logically independent functionalities will cause a mess. Subclassing is a very special relationship, often overused. Subclassing is for Is-a-Kind relationships.
If you want to visualize something, why not create a fully independent Class for that? You could simply pass your Node object to this. (Or even better, use an Interface.)
I'm rather new to Java. After just reading some info on path finding, I read about using an empty class as an "interface", for an unknown object type.
I'm developing a game in Java based on hospital theme. So far, the user can build a reception desk and a GP's office. They are two different types of object, one is a Building and one is a ReceptionDesk. (In my class structure.)
My class structure is this:
GridObject-->Building
GridObject-->Item-->usableItem-->ReceptionDesk.
The problem comes when the usable item can be rotated and the building cannot. The mouse click event is on the grid, so calls the same method. The GP's office is a Building and the reception desk is a ReceptionDesk. Only the ReceptionDesk has the method rotate. When right clicking on the grid, if in building mode, I have to use this "if" statement:
if (currentBuilding.getClass.equals(ReceptionDesk.getClass)
I then have to create a new ReceptionDesk, use the rotate method, and the put that
reception desk back into the currentBuilding GridObject.
I'm not sure if I'm explaining myself very well with this question. Sorry. I am still quite new to Java. I will try to answer any questions and I can post more code snippits if need be. I didn't know that there might be a way around the issue of not knowing the class of the object, however I may also be going about it the wrong way.
I hadn't planned on looking into this until I saw how fast and helpful the replies on this site were! :)
Thanks in advance.
Rel
You don't want to check the class of an object before doing something with it in your case. You should be using polymorphism. You want to have the Interface define some methods. Each class implement those methods. Refer to the object by its interface, and have the individual implementations of those objects return their values to the caller.
If you describe a few more of the objects you think you need, people here will have opinions on how you should lay them out. But from what you've provided, you may want a "Building" interface that defines some general methods. You may also want a "UsableItem" interface or something more generic. Hospital could be a class that implements building. ReceptionDesk could implement UsableItem. Building could have a grid of UsableItem inside it.
If rotate() was a common method to all furniture that actually did some work, you may consider making an AbstractUsableItem class that was an abstract class implementing UsableItemand providing the rotate() method. If rotate was different in each implementing class, you would have that method in the interface, but each class, like ReceptionDesk would do its own thing with the rotate() method. Your code would do something like:
UsableItem desk = new ReceptionDesk();
desk.rotate()
In your example, if your mouse click on a screen rotated the object under it, and you really did need to check to see if the object could be rotated before doing something like that, you'd do
if (clickedObject instanceOf UsableItem) {
((UsableItem) clickedObject).rotate();
}
where UsableItem was the interface or abstract class. Some people feel that all design should be done via an interface contract and suggest an interface for every type of class, but I don't know if you have to go that far.
You might consider moving in a totally different direction and having the objects themselves decide what kind of action to take. For example, the GridObject interface might specify function declarations for handleRightClick(), handleLeftClick(), etc. What you'd be saying in that case is "any class who calls themselves a GridObject needs to specify what happens when they are right-clicked".
So, within the Building class, you might implement handleRightClick to do nothing (or to return an error). Within the ReceptionDesk class, you would implement handleRightClick to rotate the desk.
Your code snippet would then become:
currentBuilding.handleRightClick(... any necessary parameters ...);
You are correct to be worried. A good rule of thumb for Object-oriented design is that whenever you use a construct like if(x instanceof Y) or if(x.getClass().equals(Y.class)), you should start thinking about moving methods up or down, or extracting new methods.
Elliot and John have both presented good ideas on very different directions you could go, but they're both right in that you should definitely move in some direction. Object oriented design is there to help your code become more legible by making branching for different sorts of behaviors more implicit. Examining what sort of object you're looking at and determining what to do based on that can defeat the purpose of using object-oriented design.
I should also warn you that an interface isn't exactly an empty class. There are some significant differences between empty, abstract classes with abstract methods and interfaces. Instead of thinking of an interface as an empty class, think of an interface as a contract. By implementing an interface, your class promises to provide each of the methods listed in the interface.
I have a hierarchy of three interfaces, grandparent, parent and child. Parent and child have a method "add", which requires different input parameters in the child. While it's no problem to add the required signature in the child, the inherited method will be pointless, so is there a way to not have it in there at all? The other methods work fine.
Maybe, to achieve what I want, I can improve the design altogether, so I'll shortly outline what the interfaces are about:
I collect meter readings that consist of a time and a value. The grandparent interface is for a single reading. I also have classes that represent a number of consecutive readings (a series), and one that contains multiple series running over the same period of time (let's just call that a table).
The table can be viewed as a series (which aggregates the values orthogonally to the time axis), and both table and series can be viewed as a single reading (the implementations providing different means of aggregation), hence the inheritance. This seems to work out fine, but for the add method. (I can add a single point to the series, but for the table I need an additional parameter to tell me to which series it belongs.)
No, you cannot avoid inheriting a method, since doing so would violate the Liskov substitution principle.
In practice, you could have implementations throw an UnsupportedOperationException, but that would be pretty nasty.
Can't you implement the inherited method with some sort of default value for the series?
Maybe it would make sense to break the interface inheritance all together. Just have specific interfaces for specific types of behaviors. Whatever classes you have that implement these interfaces can just pick the ones that make sense, and won't have to worry about implementing methods that don't make sense.
The problem with inheritance is that the focus on the language mechanism makes people think about implementation rather than semantics.
When B inherits from A, it means that every instance of B is also an instance of A. In OOP, being an instance of something means typically that you should have a sensible response to its methods and at least support their messages.
If you feel that B should not support one of the messages of A, then as far as I am concerned you have two options:
BAD - Throw an "Unimplemented" exception as you would get with the collections framework. However, this is in my opinion poor form.
Good - Accept that B is not a type of A and avoid the inheritance, or restructure it (e.g., using composition and/or interfaces) so that you don't have to rewrite the code but you do not use a subtyping relation. If your application will live over time, you don't want to have semantic issues in your hierarchies.
Thanks for putting me on the right track, I upvoted the posts I found most helpful. Since my solution was inspired by the posts, but is not posted, I'll share what I decided to do:
As the hierarchy was inspired by how the data should be viewed, while the problems arise on the semantics of how you add data, I'm going to split up the interfaces for series and table into a read and a write interface each. The write interfaces have nothing to do with each other, and the read interfaces can inherit without conflicts.
I'll make this wiki, in case someone wants to expand on this.
You might want to look at the Refused Bequest code smell.
An interface is a contract. It means that anything that implements that interface will necessarily implement the methods defined. You could technically just implement it as a dummy method (no body, simply return, whatever) but to my knowledge, it must be implemented.
You can always implement the method as empty, for example:
class A implements B{ void add(A) { /*Goes Nowhere Does Nothing*/ return;} }
but really, it's not a good idea. A better solution would be for all of your grandparents, parents, and children all be the same class with two extra methods- hasParent():boolean and hasChild():boolean. This has the benefit of being a liskov substition compatible change as well as a cleaner design.