Be wary of YAGNI and consider this answer to a similar question which asserts that Patterns are not building blocks.
The GoF State Pattern solves a problem of selection of a single behavioural object to represent a class' functionality.
Meanwhile, the GoF Composite Pattern solves a problem of combining multiple behavioural objects to represent a class' functionality.
On that basis, the two patterns are designed for two almost-opposing objectives. One pattern seeks to single out just one behavioural object, while the other pattern seeks to combine multiple behavioural objects.
You may of course find a purpose for each of them somewhere in your program to solve different problems, but it's very difficult to see how you could gain any benefit from trying to use them together to solve the same problem.
Based on your description, it sounds like you could need either the Composite pattern or the State pattern, but probably not both (yet), and probably not both together (at least not directly).
Consider looking at how much variation in behaviour/logic you need from the state pattern, versus how much of your behaviour can simply be structured as data.
- If you have a lot of state-dependent logic in your
Component classes (i.e. behaviour which follows different rules/algorithms/etc), then consider abandoning the composite pattern.
- State-dependent logic in a single
Component suggests those components have a very weak identity and shouldn't be treated as components because the state doesn't belong to the component, yet it deactivates large portions of its behaviour.
- Those components may also contain some related fields/data which might be common to all states; those could be separated out into simple data objects away from the state-specific behaviour (Remember that the state pattern is about behaviour and not about data).
- You might also have some common 'helper' methods in each component whose behaviour isn't state-specific, which could be moved into a common class.
- Consider how your code would look if you redistributed all of that Component logic into
State classes instead, possibly passing data objects into them.
- If any particular
State class starts to look too big or takes on too many responsibilities, you could apply a composite pattern just to that particular state.
- If most of the differences between your states are based on data (i.e. information which you might reasonably include in a lookup table, a JSON/XML structure, or even a database), then consider scrapping the
- When 'state' is just a description of a dataset, you only need a simple representation such as an
enum variable which can act as the key to that dataset.
- Data-driven variations in behaviour could be defined in a simple map or dictionary-like structure keyed by a state variable.
- Each variation could be a reference data object which defines rules/constraints and parameters that your components need to obey. (for example - a parameter object passed into each component and used to inform the logic of those those components).
Final (somewhat unrelated) note: Be wary of class names which sound like entities. Useful class names are often those which somebody reading your code can immediately relate either to some behavioural aspect of a program, or to a functional requirement.
Player tell you nothing about what a
Player object should be responsible for; the real danger is that inevitably leads developers down an inside-the-box type mentality toward design; in turn that often results in God Objects which become responsible for doing everything that might conceivably relate to a player.