Lets say I have a key and door. My third class (player) needs to pick up a key and open the doors. How should those objects communicate without making too much dependencies between them?
Precise answer usually (or always?) depends on the specific situation and circumstances but I think it's a good idea to try to model the real-world relations between objects.
Like in your example - the human is the only entity that actually does something (takes action). So probably this class should call key and door's methods. Key doesn't have to know or do anything. It only has to have some kind of ID (to check if that's the right one). The door has to know what key fits into its lock (have the key's ID). Nothing else. Well, it can also have some kind of Open() method (to allow player to pass through it, but that's a different thing, actually). The human takes the actions (take/produce a key, put it in the door's lock and try to open the door).
Modeling the real-world relations between objects is good... because it's proven to work! It works in real-life so it should work in your application, too (provided it's not too complex/impossible to implement).
Also, as always, try to keep things as simple as possible and use common sense - if your app or the situation your trying to implement is small/simple - it's sometimes just better to do it the easiest way you can think of without overthinking and overdesigning objects' relationships - because there's no point in it.
The simplest way to enforce a relationship without strong coupling is to use a Mediator. There could be an
Here's some C# code to illustrate. If you need clarification just leave a comment.
In this example, OnCollision is registered to the collision system, which activates it (and the other collision handlers) when two entities collide.
As you can see, this simple Unlocker class added a new set of behaviors dependent on the player, keys, and doors without creating any coupling between the entities themselves. This is especially important for object models like composition where entities are not able to implement their own behaviors.