Doesn't mattter for caching if you use views or db_query(). Caching works always the same, how the data is fetched when the cache misses is completely up to you.
- Build a cache ID to identify your cache entry. Can be a simple, hardcoded string or something complex based on arguments and so on.
- Check if can load from the cache.
- If not, rebuild data and put it into the cache with the desired expiration time.
To see some examples, you can look at the functions that use cache_get(), for example variable_initialize().
If your function is called multiple times then you probably want to combine it with a static cache, see for example archiver_get_info(). And if the data rebuilding is really slow, you can prevent it from happening multiple times by using the locking framework as variable_initialize() does.
Note that caching a single query only makes sense if it's a slow one, because a cache_get() is also a db query unless you use an alternative cache backend like Memcache.
And lastly, Views has caching already built-in and can be configured in your view. So that might be an option as well.