Indeed this is a subjective question, and there is no substitute for experience.
Design patterns is a good first step. The gang of four book (Design Patterns: Elements of Reusable Object-Oriented Software) is kind of the original bible in this area but its not an easy read. So I highly suggest Head First design patterns, I have read through most of it and its excellent. Design patterns are about solving problems by dividing the problem into manageable chunks and using previously researched techniques that are known to work and are well tested. I would say they sit in the middle between your design solution and your algorithm in terms of design. There are obvious bad ways, such as the anti-patterns which are covered in the book aswell as the good design patterns.
Martin Fowlers enterprise design patterns would be the next book after this, and it is quite a leap up in experience required to understand it. I would say i'm a good programmer and scored extremely well in university but this book is not easy, but it is very useful. These design patterns are very clever, whilst the core design patterns you should consider as your bread and butter.
As a design pattern example, look up how JUnit (Unit testing) is built, this unit testing program is built using alot of patterns and as such ends up having only a few classes but is extremely flexible.
In addition to design patterns, are design concepts like GRASP. Basically these are good programming practices.
Now as to designing an entire solution, this is what you will get with experience and practice. When making solutions you will make mistakes, you will need to rewrite and refactor code but you will learn. There are many books and designing and many more following software engineering methodologies. But i would recommend you read Eric Evans, domain driven design, tackling the complexity at the hear of software. Again not an easy read but well worth it.
But the most important thing you must consider with a design is what is right for the problem. KISS - (Keep it simple stupid, i think that's right). Basically if you building a simple application in a week and are aware it will not be used in the future. Do not overdesign/over engineer the application just keep it simple. Design patterns tend to increase the number of classes in order to make code more flexible, at the cost of this can be code complexity and time to implement. So if the application is simple do not worry about writing your business logic into a GUI, but if the application is going to be built upon or reused you really need to use a GUI design pattern like MVC,MVP or MVVM in order to have a good design.
I made the mistake of over engineering my final year project. Sure it was flexible but I never had time to implement or display all the flexibility. I built everything to an interface to avoid dependency problems and it allowed me to unit test better and swap file/DB repositories on the go. Slight problem was it took 6 weeks working 12 hours a day to program 30,000 lines of code (more if you include comments/white space :) ).
It is always a balancing act. And over time you will gain both experience and knowledge, a good design will make use of these as you learn.