Generally, option 3 is used: a sequence of commands is uploaded, and they're all tied to specific times. "burn for 15 seconds at date x time y".
Unlike your option 1 , this allows mission control to upload commands in advance. For example, the New Horizons Pluto flyby program contained thousands of commands that needed exact timing, and the spacecraft had to change its attitude often to point its instruments at their targets. That meant the main antenna wasn't pointing at Earth most of the time and couldn't receive commands in real time.
Spacecraft outside Earth orbit don't know where they are (position is determined by mission control, spacecraft don't have sensors that can accurately determine position), so that makes option 2 difficult.
Option 1 was used for a few missions, e.g. the Lunokhod Moon rovers were controlled in real time. Every mission since then has used onboard computers to store and execute commands.
Spacecraft and rovers can have some autonomy, e.g. the Mars rovers can be told "drive in direction X" and they'll drive to that point autonomously, going around obstacles, stopping for interesting science targets or when the rover can't find a safe path.