This question already has answers here:
What is the difference between association, aggregation and composition?
(21 answers)
Closed 6 years ago.
I'm having some trouble fully understanding composition and aggregation. From what i'm understanding a composition relationship means if one dies the other dies. aggregation means they're formed of that, but not necessarily dependent on that things continued existence.
This is the UML I put together for a game of hearts. Am I grasping this concept correctly?
What is composition and aggregation ?
The composition and aggregation represents a whole/part relationship (UML 2.5, section 11.5.3.1):
A binary Association may represent a composite aggregation (i.e., a
whole/part relationship).
So if you use a diamond, you should first ask yourself if it's really a whole/part relationship, before thinking how objects are created or deleted.
Then composition have additional constraints over a shared aggregation. In a composition relationship (UML 2.5, section 9.5.3):
(...) the composite object has responsibility for the existence and storage
of the composed objects. Composite aggregation is a strong form of
aggregation that requires a part object be included in at most one
composite object at a time. If a composite object is deleted, all of
its part instances that are objects are deleted with it.
Analysis of your specific diagramm
According to your diagram:
The players exists only within a game (i.e. temporary identification not accounts existing across several games). The composition could make sense, as players can be seen as parts of the game.
The hand exist only in relation to a player. That makes sense. But is it really a composition relationship ? Is the hand a part of a player ? Is the player composed of hands ? Wouldn't a player have several hands sequentially but not in the same time ? I really have my doubt about a composition here; I'd represent this with a normal 1 player to many hands association.
The game aggregates several decks. I don't know your game but I'd expect one deck. If several decks are used, and the decks only exists within a game (similarly to the players), I'd rather see a composition instead of an aggregation. Alternatively you could mean not the deck, but the deck together with its state. In this case, I'd opt for a one to many association and not a composition (the deck+state would not be a component of your game, but define the state of the game).
A deck is the aggregation of cards that exist independently of the deck. This troubles me a lot, as my world experience has always shown that a card is part of a deck. If I find an isolated card somewhere I always look for it's deck. I'd therefore rather expect a composition between cards and deck.
Finally a hand is the aggregation of several cards, which seems to make sense. Note that this is not incompatible with a composition between the deck and the card.
Related
I am currently working on a basic Disc information management system for a school project in which a user can add/remove disc information. There are two types of discs that are mentioned in the specs, Music and Game. These both have some shared attributes and so I made a superclass called Disc that had two subclasses Music and Game discs that would inherit these shared attributes. The specs also state that there needs to be a single maintainable list for both types of disc, so regardless of whether the user chooses to add music or game it will be added to a single DiscInfo list.
My question is, how can I define a list of two objects? Are objects of a subclass also objects of the superclass and so I could create a list of Disc objects in which either Music or Game objects can be added/removed?
I'm brand new to OOP and so my understanding of classes and objects is very rudimentary and I may be thinking of this wrong. Hope my question makes sense.
If the size of your list is known you can use an array type, but you can use List or vector too. Thanks to polymorphism you can put any children type from Disc into List<Disc>
So I'm trying to make a CCG type of game using javafx (similar to Hearthstone), and I was wondering if it's a very bad idea to have one class for each card, because I've done some research and most fan made card games of Hearthstone use JSON to get the card objects. For example if the game only had 4 cards with the names:
DragonMaster
Vulcan
Pirate
Chuck Norris
I'd have 4 classes, with the names respectively. Now I though this was necessary since every card would have its own behaviour, meaning one card might do something when summoned, and in this case I have a method that gets called for that action, while others might have other methods or none at all.
Now as you can probably tell, if you have 100 cards in the game, the number of classes also gets big (and that's just for the cards package, since I'm using the MVC model, the project got really big without me realizing it).
Some other information:
All concrete card classes (e.g. Vulcan) extend an abstract Card class that contains fields such as name and cost.
Inside the cards package in the model, I have two other packages before having the actual classes, one for minions and another one for spells.
Also, If I don't have a class for each card, how can I instantiate a new specific card to add to the player's hand? Is there a different solution to this "class abundance" problem, and does this actually affect performance when the game is running or even space in the jar file?
If someone could anwser my question or any kind of help I'd be very appreciated.
Having thousands of classes will not impact performance in any noticeable way. You can even pre-compile them ahead of time or cache them.
That said, many game engines are using a entity-component approach to represent game entities and keep things like effects as different functions.
This way you can combine different effects cards have in ways that can't be done with single-inheritance.
Below is a link that describes the approach.
https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system
You could adapt this gradually.
For example, your cards could be just one type of entity.
class Card {
int mana;
String name;
Effect[] effects;
Trigger[] triggers;
}
Effects could be pieces of code that act on the playfield and the current card.
interface Effect {
void affect(Playfield pf);
}
Triggers could be event listeners relevant to the card.
I.e. there could be a trigger that fires when the opponent plays a card.
etc.
I am no expert in this field, but I think while your approach would work, it could make maintainability and scaling more difficult.
Another alternative you can try is to store the characteristics of your cards in a database (or some kind of properties file). In this case, you just need a common Card class, and it loads its values from database.
class Card {
int id;
String name;
int cost;
int speed;
OnSummonEffect summonEffect;
}
interface OnSummonEffect { ... }
abstract class StatBoostEffect implements OnSummonEffect { ... }
class AttackBoostEffect extends StatBoostEffect { ... }
Card Table
CardID Name Cost Speed SummonEffect
1 DragonMaster 5 10 com.foo.bar.AttackBoostEffect
2 Vulcan 3 12 com.foo.bar.SomeSummonEffect
Although saving the class name may not sound elegant (and it probably has its own side effects), but this approach makes it easy to add new things.
Adding a new card type is simply adding a new entry to the database table, and potentially adding new "effect" class to the project. If you decide to change some attributes (or add new attributes) to the card, you just need to add/change column in database table and then that single Card class. If you made one class for each card type, you would have to change the base card, then change every single card class.
I'm creating a 2D turn-based multiplayer (no AI) board game in Java using the MVC pattern in which there are a lot of rules and conditions, I can't figure out a good pattern to implement them, for example:
The player can choose a character from a pool of 12: They have similarities between them but each character could move differently, could use different items, etc.
The movement ability, which could already be different based on the character, could change during the game by using items (for just one turn) or after some events (for all the game). For example moving by 3 cells instead of 2.
All these rules could be different based on the selected game-mode which could also change the winning conditions and some game strategies.
Which patterns could be suitable for this? Especially the fact that different characters could have different behaviors depending also on the gamemode and the state of the game.
I know there are already a lot of questions on game patterns on SO but I could not find something suitable to this.
If I had to design this game, I would try to identify different objects that are hidden in the problem statement as follows :
The player can choose a character from a pool of 12
Hmmm. So I am going to need a Player and Character class.
They have similarities between them but each character could move
differently, could use different items
Ok. So there is behavior that is common to each Character but Characters can also have additional behavior that is different from the common behavior. Let's add methods in Character for each behavior that is common across characters.
But what about the behavior that is only applicable for a particular type of Character? Ok so I definitely need a way to add behavior to my characters at runtime.
Hmmmm. Let's create an interface called Behavior which contains a method called.. umm.. behave. Let's create a couple of classes that implement this interface and implement the behave method.
So far so good. We have a Character class that can be used to instantiate one of 12 characters. We have a Behavior hierarchy for additional behaviors not common across characters. We now need to make these two classes work together in such a way that we can add behavior at runtime. Throughout my career, I have been told to favor composition over inheritance. So I guess I am going to make character have-a Behavior by adding a Behavior reference in Character. There is a name for this pattern.. this is the Strategy pattern.
The most important take-away from the above explanation is that you don't look at a problem and say what design pattern can I apply?. Instead, you come up with an initial draft of what your design will be like and say this looks like the XYZ pattern
There are lot of requirements that I have not covered in this answer. The idea of this answer is to explain to you the kind of thought process you can put in to come up with an initial draft of your design and keep evolving it rather than over-designing right at the beginning.
Take a look at ECS (entity component system) architectural pattern and DDD methodology. DDD was created specifically for application with complex domain logic and games usually has it.
Some useful links:
http://en.wikipedia.org/wiki/Entity_component_system
http://en.wikipedia.org/wiki/Domain-driven_design
To fully understand DDD you HAVE TO read Eric Evans book called Domain Driven Design.
I am having some troubles with Composition and Aggregation relationships in UML, I do understand the whole/part relationship so if a class cannot exist without its whole then it makes it a strong composition relationship and if it still can exist without its whole then it makes it a weak aggregation relationship.
However sometimes it gets a little more tricky than that when dealing with real software requirements. I have a class diagram below with all necessary, attributes, operations and properties included which are all correctly shown in UML standards however I am unsure about my relationships:
1 Interface and 6 classes
Could someone confirm if my relationships are correct or not?
Many Thanks
There are a few issues. The best example of composition is Maze to Location. Your connector has the diamond on the wrong end. The class that consists of the other class has the diamond, so Maze consists of Locations. Maze should have the diamond.
The Species - Snake relationship is suspect since there are many species besides snakes and species don't consist of snakes. I also don't think that Explorer consists of Stones. The explorer-stone relationship is a straight (if I understand your application) 1 to many relationship.
I would also add multiplicity to the diagram to clarify 1:1, 1:many, etc. Please correct your diagram and repost.
It is vice versa. The black rhombus should be at the side, that holds or simply is the set of the objects from the other side of connection.
Also an occupant can exist without location (an explorer before the adventure), so it is rather aggregation dependency, not composition. As for maze, the maze IS a composition of locations, OK. Explorer to stone dependency is again aggregation - stone can be without Explorer easily.
Also, I am not sure that stone should descend directly from Occupant. I'd define CaveObject class (because Object is already busy) and derive Stone and Occupant from it, and Snake and Explorer from the last. And I'd add an interface TemporaryOccupant, and make Explorer to implement it. In that interface I'll put functions to move from one location to another.
As for Species/Snakes, I am afraid, I am at lost - what belongs to what? Rather, species should be another interface and both the snake and the Explorer should implement it, too.
BTW, I see here another error: You connect Snake and Species - it IS an attribute of other class with the type of another class already. Don't declare it as one more parameter in the class rectangle.
Your Explorer has only getter for Name, but no Setter. Your drop() has no parameter to set what will be dropped.
I'm designing a game, but I can't quite get my head around the inheritance structure. I'm normally fairly good at it, but this one just has too much overlap and I can't decide on it all.
I'm seeking to model sailing vessels - think the Age of Sail. Presumably therefore everything extends a Vessel class.
There are then several types of vessel style: rowed (galleys, canoes), square-rig, fore-and-aft rig, with different behaviour. Each of these is further subdivided into several other types. I can't decide whether this should be a series of interfaces or extensions of Vessel. Note also that there can be some cross over (a vessel can be both rowed and square rigged) which leads me to think interfaces?
Ships also have different behaviours: merchant vessels, men of war, privateer, pirates. I really can't work out whether this should be an interface or an extension of another class. There is no crossover of type in this case, however.
Finally there are several behaviours which individual ships can have. Merchants may be in a convoy (defend themselves) or independent (run away). Men of war almost always attack unless heavily outgunned... but may work in fleets, squadrons or independently. Privateers and pirates only attack if weaker - usually independently but occasionally in pairs. I'm assuming that this should be an interface too?
My big problem is that each style of ship (frigate, battleship etc) can fulfil almost any of these roles, so I can't build a simple solid inheritance structure. Frigate can't extend man-o-war because some are privateers. Sloop can't extend square rigged because some are fore and aft rigged. etcetc.
Any thoughts would be appreciated, I'm at a bit of a loose end.
Thanks
Make the "behavior" part as interfaces. That will help you assigning different behaviors to different ships without problem. Strategy Pattern is helpful here. In a nutshell, it states that the changeable and the constant properties should be separated.
For different means of movements, composition sounds like the most suitable answer at this moment.
Regarding the "but may work in fleets, squadrons or independently. Privateers and pirates only attack if weaker - usually independently but occasionally in pairs." part, I guess this has nothing to do with the inheritance tree. You can make "groups" of classes depending up on your need.
This might help you:
"There are then several types of vessel style:..." is specifying different possible behaviors. So "Movable" interface and its subclasses are for that. In the "Vessel" class, you can have a member of type "Movable". Since "Movable" is an interface, any class which implements it, is assignable to this member. So any subclass of Vessel can have any possible behavior, which we cna change at runtime as well. You can also make it an ArrayList. (Not sure if you actually want to do it or not). But if you need multiple different behaviors for a same vessel, you can do it.
When you say "Ships also have different behaviours:..." it feels like separate classes extending Vessel will satisfy this requirement. The sentence "There is no crossover of type in this case, however." makes life easier.
For the nest para "Finally there are several behaviours which individual ships can have...", you should add one more member for different possible behaviors. It will mostly be an ArrayList as one vessel will have multiple attack modes.
Fro the last para, if you can give some more details, I may be able to give some more ideas.
Ok, here are some ideas:
Vessels have one or more means of propulsion (oars, sails, etc.), which you can model by composition (e.g. have a list of propulsion methods).
Vessels use one of a variety of strategies (use the strategy pattern -- see http://en.wikipedia.org/wiki/Strategy_pattern -- for this)
Strategies which depend on the presence of other nearby ships will need some way of querying for those other ships -- so you'll need some sort of data structure that allows you to find which objects are near which other objects (look into the sort of data structures that are used for broad-phase collision detection)
As an alternative to the strategy pattern, you could switch to using a component-based design. In this setup, a vessel would be composed of one or more propulsion components, a strategy component, etc. You could then combine individual components as you see fit to make different vessels.
As an extra bonus, component-based designs are very helpful if you want your game to be data-driven, because you can just write a saver/loader for each different type of component, rather than for each possible type of vessel.
You might want to see here if you're interested in this sort of approach:
http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/
I want to provide a bit of advice based on the second paragraph of Bhusan's answer, which I quote here in full:
"Regarding the "but may work in fleets, squadrons or independently. Privateers and pirates only attack if weaker - usually independently but occasionally in pairs." part, I guess this has nothing to do with the inheritance tree. You can make "groups" of classes depending up on your need."
This leads me to believe that you additionally may want to consider the Composite pattern for certain groups of ships, at least those that are comprised of ships that all share the same behavior. See http://en.wikipedia.org/wiki/Composite_pattern where it is written that "the composite pattern describes that a group of objects are to be treated in the same way as a single instance of an object."
For instance you say "Merchants may be in a convoy (defend themselves)", but presumably they can defend themselves individually as well? This is all easier said than done of course, and my advice to you is to not over-think it and start with a very small subset of what you want to do as a protoype
You should separate the types and use the strategy pattern.
Immutable properties should be bound to the inheritance tree (e.g. a frigate won't turn into canoe, these are exact, non-behavioral types, inheriting from vessel) and everything that may change should be stored as references to behavioral types which are intrachangable. (Man-o-war is a behavioral type)
AI should be handled separately, for instance with states, but that is also have to be in a different module in your architecture.
Instead of thinking about it as strictly inheritance, I think you need to think about object Composition and how that can help make things easier.
For example: a Ship has a Behaviour. (Composition... the ship delegates to the behaviour to determine how to react to X situation)
A Pirate is a Behaviour (Inheritance from a Behaviour interface)...
You should not extend the Vessel class. Rather, a Vessel object should contain other objects that describe it. (This is known as Dependency Injection, to be annoyingly pedantic--forget I said that.) You have a Propulsion class, with instances for square-sails, fore-and-aft, and oars. You might want special instances of each for big and small hulls. You have a Behavior class to handle their attitude. Sometimes a simple integer works as well as a class. Your Armament class could be, instead, just a number of guns. (Or two numbers, one for poundage.) If you expect to ram, or have a ship loaded with rockets, or need to distinguish between long guns and carronades, you might need to go back to using the a class.
This lets you switch characteristics on the fly if you want--though you probably don't. Still, you can go from sail to using sweeps, or switch bold ship-of-the-line behavior with save-the-cargo behavior of a merchant to implement a captain losing his nerve. Anyway, it's there if you need it.